Special #define option in C - c

I have a structure A such that A has fields v0 and v1.
There is an array of A's:
A St[3];
I'd like to define B like that:
#define B[x] St[x].v0
I can't insert x as a parameter to define.
Is there some way to do that in C?
My purpose is to be able to replace each instance of St[x].v0 with B[x].

A macro that substitutes parameters is called a function-like macro, and the C standard only provides for function-like macros using parentheses, not brackets.
You can use below method:
#define B(x) St[x].v0

According to the C reference, the defintion of #define is
#define <identifier>[( parameters, ... )] [replacement-list]
You must not use square brackets within an <identifier> (see C99 standard) and therefore your suggested solution would not be properly processed by the preprocessor.
What would work instead is
#define B(x) St[x].v0 // note the brackets
where you would pass additional parameters to the macro (using parentheses).
However this will obfuscate your code and most probably confuse users/readers of your code. See also why you should be careful with macros.

You can have
#define B(x) St[x].v0
ant then replace each instance of St[x].v0 with B(x).
I'm afraid it's impossible to do it with [], you'd need operator overloading (like the one in C++) for that.

Related

C macro wrapping

So I encountered the following code in a library for C for RF communication :
#define __COMB(a,b,c) (a##b##c)
#define _COMB(a,b,c) __COMB(a,b,c)
Which is basically used to create various names for constants and functions. It just concatenates the parameters.
What I don't get is the 2nd line. Is there a reason to wrap the macro?
If it's just a naming issue, why not just write :
#define _COMB(a,b,c) (a##b##c)
The library can be found here.
Thanks in advance!
This is a hack to trick the C preprocessor to pre-expand the parameters before they're concatenated. This kind of decoupling is required in certain some situations, for example if __COMB is to be used in a preprocessor macro parameter stringification.
Double macro is used to make sure, that it will work even when parameters are also macros.
Without double macro we would get XXYYZZ instead of xyz:
#define XX x
#define YY y
#define ZZ z
_COMB(XX, YY, ZZ)

Can a C macro definition refer to other macros?

What I'm trying to figure out is if something such as this (written in C):
#define FOO 15
#define BAR 23
#define MEH (FOO / BAR)
is allowed? I would want the preprocessor to replace every instance of
MEH
with
(15 / 23)
but I'm not so sure that will work. Certainly if the preprocessor only goes through the code once then I don't think it'd work out the way I'd like.
I found several similar examples but all were really too complicated for me to understand. If someone could help me out with this simple one I'd be eternally grateful!
Short answer yes. You can nest defines and macros like that - as many levels as you want as long as it isn't recursive.
The answer is "yes", and two other people have correctly said so.
As for why the answer is yes, the gory details are in the C standard, section 6.10.3.4, "Rescanning and further replacement". The OP might not benefit from this, but others might be interested.
6.10.3.4 Rescanning and further replacement
After all parameters in the replacement list have been substituted and
# and ## processing has taken place, all placemarker preprocessing tokens are removed.
Then, the resulting preprocessing token sequence
is rescanned, along with all subsequent preprocessing tokens of the
source file, for more macro names to replace.
If the name of the macro being replaced is found during this scan of
the replacement list (not including the rest of the source file's
preprocessing tokens), it is not replaced. Furthermore, if any nested
replacements encounter the name of the macro being replaced, it is not
replaced. These nonreplaced macro name preprocessing tokens are no
longer available for further replacement even if they are later
(re)examined in contexts in which that macro name preprocessing token
would otherwise have been replaced.
The resulting completely macro-replaced preprocessing token sequence
is not processed as a preprocessing directive even if it resembles
one, but all pragma unary operator expressions within it are then
processed as specified in 6.10.9 below.
Yes, it's going to work.
But for your personal information, here are some simplified rules about macros that might help you (it's out of scope, but will probably help you in the future). I'll try to keep it as simple as possible.
The defines are "defined" in the order they are included/read. That means that you cannot use a define that wasn't defined previously.
Usefull pre-processor keyword: #define, #undef, #else, #elif, #ifdef, #ifndef, #if
You can use any other previously #define in your macro. They will be expanded. (like in your question)
Function macro definitions accept two special operators (# and ##)
operator # stringize the argument:
#define str(x) #x
str(test); // would translate to "test"
operator ## concatenates two arguments
#define concat(a,b) a ## b
concat(hello, world); // would translate to "helloworld"
There are some predefined macros (from the language) as well that you can use:
__LINE__, __FILE__, __cplusplus, etc
See your compiler section on that to have an extensive list since it's not "cross platform"
Pay attention to the macro expansion
You'll see that people uses a log of round brackets "()" when defining macros. The reason is that when you call a macro, it's expanded "as is"
#define mult(a, b) a * b
mult(1+2, 3+4); // will be expanded like: 1 + 2 * 3 + 4 = 11 instead of 21.
mult_fix(a, b) ((a) * (b))
Yes, and there is one more advantage of this feature. You can leave some macro undefined and set its value as a name of another macro in the compilation command.
#define STR "string"
void main() { printf("value=%s\n", VALUE); }
In the command line you can say that the macro "VALUE" takes value from another macro "STR":
$ gcc -o test_macro -DVALUE=STR main.c
$ ./test_macro
Output:
value=string
This approach works as well for MSC compiler on Windows. I find it very flexible.
I'd like to add a gotcha that tripped me up.
Function-style macros cannot do this.
Example that doesn't compile when used:
#define FOO 1
#define FSMACRO(x) FOO + x
Yes, that is supported. And used quite a lot!
One important thing to note though is to make sure you paranthesize the expression otherwise you might run into nasty issues!
#define MEH FOO/BAR
// vs
#define MEH (FOO / BAR)
// the first could be expanded in an expression like 5 * MEH to mean something
// completely different than the second

Why does GCC's __attribute__((...)) syntax use double parentheses?

The documentation for GCC's __attribute__((...)) syntax indicates that attributes must be surrounded by double parentheses, but does not give a rationale for this design decision.
What practical reason would have caused GCC's designers to require this? Does it have anything to do with the preprocessor's handling of double parentheses?
To make it easier to eliminate it for different compiler. If you have portable code, you have to remove them for other compilers, so you do
#ifndef __GNUC__
#define __attribute__(x)
#endif
The problem is that attributes have various number of arguments and you can combine multiple attributes in one __attribute__ declaration, but C only introduced variadic macros in C99. With double parenthesis the above definition does not need variadic macros.
probably the idea is that you can declare a simple macro that helps to ignore all this in any other C and C++ compiler. If you wouldn't have the second pair of parenthesis that macro would be necessarily one with .... So for compilers that don't support that you would be screwed.
Edit: With this syntax it can simply look like
#ifdef __GNUC__
# define attribute(X) __attribute__(X)
#else
# define attribute(X)
#endif
and then you would use attribute for your function declarations, e.g.

C error: missing whitespace after the macro name

I wrote the following macro:
#define m[a,b] m.values[m.rows*(a)+(b)]
However gcc gives me this error:
error: missing whitespace after the macro name
What is wrong and how do I fix it?
You cannot use [ and ] as delimiters for macro arguments; you must use ( and ). Try this:
#define m(a,b) m.values[m.rows*(a)+(b)]
But note that defining the name of a macro as the name of an existing variable may be confusing. You should avoid shadowing names like this.
I'm not familiar with any C preprocessor syntax that uses square brackets. Change
#define m[a,b] m.values[m.rows*(a)+(b)]
to
#define m(a,b) m.values[m.rows*(a)+(b)]
And it should work.
You cannot have such a macro that will expand when you supply arguments in square brackets. Wherever you got the idea that macros are a smart text-substituting tool, it's just the other way round: macros are extremely obtuse and stupid text-substitution mechanism. What you're trying to do with a macro is absolutely unwarranted - just write a named function.

Undef'ing a function-like macro

In the C/C++ there are 2 types of macro:
#define ABC /* usual */
und
#define FUNC(a) /*function-like*/
But how can I undefine them?
Update: So there is no difference between undefing "constant-like macro" and "function-like macro"?
#undef ABC
#undef FUNC
#undef "cancels" out a previous #define. The effect is as though you never had a previous #define for a particular identifier. Do note that #defines do not respect scope, so it's best to use them only when you need to.
Also note that it doesn't matter if one macro identifier uses the "usual" syntax while another uses a "function-like" syntax. #define ABC and #define ABC(A) both define a macro named ABC. If you have both, without #undefing one of them, the latest one "overrides" the other. (Some compilers may emit a warning if this happens.)
#undef ABC
#undef FUNC

Resources