What do two adjacent pound signs mean in a C macro? - c

I'm taking a look at an application that defines a large set of constant arrays. What really confuses me is the use of two pound signs next to each other in a macro. For example:
#define r0(p,q,r,s) 0x##p##q##r##s
What do those two pound signs mean?

## provides a way to concatenate actual arguments during macro expansion.

## concattenates symbols. So for example if the value of p is ab, 0x##p would become 0xab.

Als and sepp2k give correct answer.
However I would like to add, that this macro seems to be completely unnecessary.
unsigned int value = r0(b,e,a,f);
can be replaced by better and shorter:
unsigned int value = 0xbeaf;

Related

Is it possible to redefine "." using macros in C?

I have a (possibly faulty) school assignment regarding the C-preprocessor, in which I should essentially define a macro which allows
Today is the 9.
to compile to
int a = 9;
Note the "." after the 9. The rest of the program is similar, I have no problem with that.
Now I replaced "Today" by int (#define Today int), "is" by a, "the" by = but I don't know what to do with the ".", given if I just blindly replace it by doing
#define . ;
I get a compile-time error.
Is it even possible to do something with the dot?
Is it possible to redefine "." using macros in C?
No.
given if I just blindly replace it by doing
#define . ;
I get a compile-time error. Is it even possible to do something with
the dot?
No, it is not possible.
In the first place, the . in the text presented is not a separate token according to C's rules. It is part of 9., a floating-point constant. Macro replacement operates only on complete tokens.
In the second place, macro replacement is not a general search / replace. Macro names must be C identifiers, which start with either an underscore or a Latin letter, and contain only underscores, Latin letters, and decimal digits. Thus, it is not possible to define either . by itself or the full 9. as a macro name.
#define Today int
#define is a
#define the = (int)
void foo(void)
{
Today is the 9.;
printf("%d\n", is);
}

C Stringize result of equation

I have read lots on stringizing macros, but I obviously don't quite understand. I wish to make a string where the argument to the macro needs to be evaluated first. Can someone please explain where I am going wrong, or perhaps how to do this better?
#define SDDISK 2 // Note defined in a library file elsewhere ie not a constant I know)
#define DRIVE_STR(d) #d ":/"
#define xDRIVE_STR(x) DRIVE_STR(x)
#define FILEPATH(f) xDRIVE_STR(SDDISK + '0') #f
const char file[] = FILEPATH(test.log);
void main(void)
{
DebugPrint(file);
}
The output is: "2 + '0':/test.log",
But I want "2:/test.log"
The C PREprocessor runs before the compiler ever sees the code.
This means that the equation will not be evaluated before it is stringified; instead, the preprocessor will just stringize the whole equation.
In your case just removing the +'0' will solve the problem as the value of SDDISK does not need casting to a char before it is stringified.
However, should you actually need to perform a calculation before stringizing you should either:
Use cpp's constexpr.
Complain to your compiler vendor that a constant expression was not optimized.
Use a preprocessor library to gain the wanted behaviour.

Is there a one-macro way to prefix and quote C macro argument

So when looking into getting my define macro to work, I found the # and ## macro helpers, and used them to simplify my macro. The key part of the macro sets a variable to a string containing the name of the variable (but not the variable name alone). As a simplified example, let's take a macro called SET(X) that should expand SET(something) into something = "pre_something".
The only way I've found to do it so far is with two macros like #define QUOTE(X) #X and #define SET(X) X = QUOTE(pre_##X). However, using multiple macros seems excessive, and may cause problems with further macro expansion (I think). Is there a cleaner, one-line way of doing the same thing?
#define SET(x) x = "pre_"#x
C does string concatenation at compile time, so two string literals next to each other are concatenated.
"hello " "world" -> "hello world"

Opposite of C preprocessor "stringification"

When using C preprocessor one can stringify macro argument like this:
#define TO_STRING(x) "a string with " #x
and so when used, the result is as follows:
TO_STRING(test) will expand to: "a string with test"
Is there any way to do the opposite? Get a string literal as an input argument and produce a C identifier? For example:
TO_IDENTIFIER("some_identifier") would expand to: some_identifier
Thank you for your answers.
EDIT: For those wondering what do I need it for:
I wanted to refer to nodes in a scene graph of my 3D engine by string identifiers but at the same time avoid comparing strings in tight loops. So I figured I'll write a simple tool that will run in pre-build step of compilation and search for predefined string - for example ID("something"). Then for every such token it would calculate CRC32 of the string between the parenthesis and generate a header file with #defines containing those numerical identifiers. For example for the string "something" it would be:
#define __CRC32ID_something 0x09DA31FB
Then, generated header file would be included by each cpp file using ID(x) macros. The ID("something") would of course expand to __CRC32ID_something, so in effect what the compiler would see are simple integer identifiers instead of human friendly strings. Of course now I'll simply settle for ID(something) but I thought that using quotes would make more sense - a programmer who doesn't know how the ID macro works can think that something without quotes is a C identifier when in reality such identifier doesn't exist at all.
No, you can't unstringify something.
//unstringify test
enum fruits{apple,pear};
#define IF_WS_COMPARE_SET_ENUM(x) if(ws.compare(L#x)==0)f_ret=x;
fruits enum_from_string(wstring ws)
{
fruits f_ret;
IF_WS_COMPARE_SET_ENUM(apple)
IF_WS_COMPARE_SET_ENUM(pear)
return f_ret;
}
void main()
{
fruits f;
f=enum_from_string(L"apple");
f=enum_from_string(L"pear");
}
You can create an identifier from a string, this operation is called token-pasting in C :
#define paste(n) x##n
int main(){
int paste(n) = 5;
printf("%d" , x5);
}
output : 5

Why one needs two brackets to use macros in C?

KdPrint(("Enter HelloWDMAddDevice\n"));
What's the reason for doing that?
That is so you can pass an entire argument list to the macro and have it pass it on to a function that takes a variable number of arguments.
I would bet anything that the definition of that macro is:
#if DEBUG /* or something like it */
#define KdPrint(args) (printf args)
#else
#define KdPrint(args) /* empty */
#endif
Or similar to some other function that works just like printf.
If it were defined as printf(args), then you could only pass the single string argument, because an argument to a macro can't contain a comma that isn't inside a nested parenthesis.
It causes everything inside the parens to be treated as a single parameter to the macro. In the example shown, it can allow for varargs types of parameters:
KdPrint(( "My info is %s\n", "my name" ));
As well as
KdPrint(( "fn %s ln %s\n", "my", "name" ));
If the macro in question was not well written using parentheses, it might be necessary because of operator precedence. Take this macro for example:
#define MY_MACRO(a) a * 11
Well, if you did this:
int b = MY_MACRO(1 + 2);
b, instead of being 33 like it should, would actually be replaced with int b = 1 + 2 * 11 which is 23 and not 33. If your macro isn't written like that, though (without parenthesis around the a) then it's unnecessary.
If this is the KdPrint() that you are talking about, then this is because you can use KdPrint() macro with format arguments, and it is not a variable length macro.
For example, you can do:
KdPrint(("The answer is %d\n", 42));
and so on.
For your specific example, I cannot tell you, because I don't know what is XdPrint.
But in a more general case, it is because a macro I just like a search and replace. Suppose you have:
#define MULT(a,b) (a*b)
If you call MULT(1+1, 2+2), it would become 1+1*2+2, and result as 5 instead of 8 as you would expect. Doing MULT((1+1), (2+2)) would gives you the expected result. That is why you need to double the brackets.

Resources