C compiling error: stray '##' in program - c

I was working with an embedded kernel source when I saw something like this:
#define OMAP_SYS_TIMER_INIT(name, clkev_nr, clkev_src, clksrc_nr, clksrc_src) \
static void __init omap##name##_timer_init(void) \
{ \
omap2_gp_clockevent_init((clkev_nr), clkev_src); \
omap2_gp_clocksource_init((clksrc_nr), clksrc_src); \
}
and when I tryed to make a program that used this ## thing (that I don't know the name) to see what it could really do I didn't got it to work. Below is what I did to test it's function. I just want to see if the argument inside the ## is literal or not, but something is clearly missing in my code for it to compile...
#include <stdio.h>
#include <stdlib.h>
#define DEFINE_1 2
#define DEFINE_2 4
#define DEFINE_3 6
#define DEFINE_i 9
int main(void)
{
int i;
for(i=1;i<4;i++) {
printf("numero %d = %d\n",i,DEFINE_##i##);
}
return EXIT_SUCCESS;
}
The output of gcc is:
test.c: In function ‘main’:
test.c:14:5: error: stray ‘##’ in program
test.c:14:33: error: ‘DEFINE_’ undeclared (first use in this function)
test.c:14:33: note: each undeclared identifier is reported only once for each function it appears in
test.c:14:42: error: expected ‘)’ before ‘i’
test.c:14:42: error: stray ‘##’ in program
Anyone knows what is wrong? Thanks

It's the token concatenation operator for the C preprocessor. The reason your example doesn't compile is because you're not using the ## operator within a macro (i.e. #define statement).
Here's another post with some more information.

## means concatenation at time of preprocessing.
http://gcc.gnu.org/onlinedocs/cpp/Concatenation.html

You can use ## in the preprocessor directives only.

## is used for concatenation in C preprocessor macros.
In your example, the idea is to concatenate omap with the function name. For example
OMAP_SYS_TIMER_INIT(foo, ...)
will create a function named omapfoo.

## is token pasting operator and you can only use it in a macro definition. You cannot use it outside a macro definition.

Maybe what you are trying to do is, DEFINE_ and (i=1) will concatenate using ## to form "DEFINE_1" and that will be your macro with value 2. Right? If that's the case, the problem is that, macro is preprocessor and value will be get in lined before execution. So it looks for DEFINE_i and there is no such macro. Keep it in mind i=1,2,3.. and so on during runtime.

Related

Enum error, variable undeclared

So I have some code that is throwing me an error and I am not sure why. I am using a macro to generate myself a string array and an enum that I can use to access the string array in a intuitive way. My compiler is complaining about my macro but the rest of my code seems to work as if the macro successfully created the enum which has me quite confused.
The macro is as follow
#define FOR_EACH_PHASE(PHASE) \
PHASE(init) \
PHASE(framerate) \
PHASE(priority) \
PHASE(time) \
PHASE(powersave) \
PHASE(performance) \
PHASE(response)
#define GENERATE_ENUM(ENUM) AI_phase_##ENUM,
#define GENERATE_STRING(STRING) "AI_phase_"#STRING,
typedef enum PHASE_ENUM PHASE_ENUM_t;
enum PHASE_ENUM {
FOR_EACH_PHASE(GENERATE_ENUM)
END
};
static const char* PHASE_STRINGS[] = {
FOR_EACH_PHASE(GENERATE_STRING)
};
Lines such as these seems to compile without error
struct phase_profile* set_defaults;
set_defaults = AI_phases_get_name(PHASE_STRINGS[AI_phase_framerate]);
But the compiler is giving me the following error for each line of my FOR_EACH_PHASE macro
error: 'performance' undeclared (first use in this function)
Any ideas from anyone that knows more about this than me?
Cheers
I don't have the required reputation to comment so I am posting this as an answer.
I believe you need this:
https://www.codeproject.com/Articles/32000/Improving-C-Enums-Adding-Serialization-Inheritance
I use it for some years now and it is fine!

Print a deprecation warning when using a macro in a #if statement

I want to deprecate a macro in such a way that it will print a nice warning even if used inside of a #if statement.
This answer is very nearly what I want, but it throws an error when the macro is accessed from within a #if statement.
#include <stdio.h>
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") 0
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT
return 1;
#else
return 2;
#endif
}
The error is:
error: missing binary operator before token "("
Bonus points if you can find me a cross-platform compatible solution!
EDIT
I'm trying to handle a breaking change in a library gracefully - I want users to have a nice, clear warning (or error) whenever they use an old macro, so it will be clear that they need to migrate their code to using the new macro. These pragma solutions only work if the value of that constant is used in code, not if the value is accessed in a preprocessor directive.
According to the answers provided below, it seems like there's not a solution to this problem (except possibly when using clang?). Thanks, everyone.
I want to deprecate a macro in such a way that it will print a nice
warning even if used inside of a #if statement.
I was going to suggest the comma operator, but that doesn't seem to work because the _Pragma macro probably yields no real code. Also, gcc, at least, explicitly says you can't do what you suggested with _Pragma():
https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html
The standard is unclear on where a _Pragma operator can appear. The
preprocessor does not accept it within a preprocessing conditional
directive like ‘#if’. To be safe, you are probably best keeping it out
of directives other than ‘#define’, and putting it on a line of its
own.
PS - clang 8.1.0 didn't error on your program and gave the warnings you want ...
As #jschultz410 mentions, what you are trying to do is explicitly forbidden in gcc (see https://gcc.gnu.org/onlinedocs/cpp/Pragmas.html).
Nested macros seem appropriate for such a use case:
#include <stdio.h>
#define DEPRECATED_CONSTANT_VALUE 0
#define DEPRECATED_CONSTANT _Pragma ("GCC warning \"Deprecated constant!\"") DEPRECATED_CONSTANT_VALUE
#define DEPRECATED_FUNCTION(...) _Pragma ("GCC warning \"Deprecated function!\"") printf(__VA_ARGS__)
int main() {
// Prints a warning (good)
int n = DEPRECATED_CONSTANT;
// Prints a warning (good)
DEPRECATED_FUNCTION("%d\n", n);
// Throws an error (bad)
#if DEPRECATED_CONSTANT_VALUE
return 1;
#else
return 2;
#endif
}
Yes, this is kind of gross, but in the land of preprocessor logic we're already giving up on any kind of design elegance in the first place. At least this way the macro interface is maintained in non-preprocessor code. (Yes, this would not print the preprocessor warning in the #if statement, but unfortunately that's not possible with gcc).

Calling a C macro with other macros as arguments

I am having issues while trying to pass a macro constant as an argument to a macro function.
Consider the following code -
#define ERROR 10
#define MAIN "Main:"
#define LOG(lvl,mod,fmt,...) \
char msg[256] = {0}; \
snprintf(msg, 256, "%s: %d: "fmt,mod,lvl,##__VA_ARGS__)
int main()
{ ....
LOG(ERROR, MAIN, "This is a log statement.\n"); // Doesn't compile
LOG(10, "Main:", "This is a log statement.\n"); // Compiles
....
}
The second log statement compiles but the first log statement generate the following compilation error -
error: expected `)' before ‘;’ token
error: expected primary-expression before ‘,’ token
error: expected `;' before ‘)’ token
Why is this happening? I want to be able to define a set of Logging levels and Modules constants, and use them while invoking the LOG() macro.
One problem with your macro is that it declares a variable at a random spot in a block of code, which C89 does not allow: you were allowed to declare variables only at the top of a block. Even with C99 compiler, the problem does not go away, because now you can introduce multiple declarations of the same name in the same scope, which is prohibited.
You can use the do/while(0) trick to solve this problem:
#define LOG(lvl,mod,fmt,...) do {\
char msg[256] = {0}; \
snprintf(msg, 256, "%s: %d: "fmt,mod,lvl,##__VA_ARGS__) \
} while(0)
There are three two issues I can see:
You will have multiple msg variables within the same scope.
You are missing a comma (as pointed-out by #Ninetainedo).
You do nothing with the formatted string.
I would prefer to declare a global logger() function that accepts a logging-level and use macros to shorten calling it.

Pasting macro on linux not working

Program below runs fine on windows. But compilation error occurs on linux
"error: pasting "." and "config" does not give a valid preprocessing token"
Any reason??? i cant understand why....
#include <stdio.h>
typedef struct pr {
int config;
}pr_t;
#define JOIN(x,y) x.##y
void main()
{
pr_t temp = {5};
printf("Value %d\n", JOIN(temp, config)); //temp.config
return 0;
}
Try without the ## :)
#define JOIN(x,y) x.y
The macro concatenation operator, ##, should only be used between two macro parameters. You have a period between them which serves to delimit the two parameter names. So as ykatchou suggested, just edit out the ## operator from the macro definition:
#define JOIN(x,y) x.y
which should still work fine in your windows compiler.
Two tokens that don't together form a valid token cannot be pasted together using ##. The compiler error says that clearly:
error: pasting "." and "config" does
not give a valid preprocessing token
As suggested by others you can drop ## altogether.
More info here.
It's to do with trying to paste a literal string and a token together. This behaviour was changed in gcc 2.7 onwards, see for example the info here:
http://weblog.pell.portland.or.us/~orc/2004/12/30/000/index.html
You should be able to remove the ## and simply concatenate the operators:
#define JOIN(x,y) x.y

Invalid preprocessor token warning message

I have a bunch of generated functions from a supplier's tool are required to be defined by me.
Since the inner functionality of each and every one of these functions are exactly the same, I figured I could use a macro to make my life easier.
Here is the offending warning:
pasting "<function_name>" and "(" does not give a valid preprocessing token
Now, I define my macro as follows:
#define HANDLE_FUNCTION(x) \
void <function_prefix>_ ## x ## (void) \
{ \
x ## _Flag = TRUE; \
}
In my code I then write:
HANDLE_FUNCTION(fn1)
HANDLE_FUNCTION(fn2)
...and so on
Any thoughts on why this occurs?
Remove the second ##, it has no use (you don't want to make one symbol of function_name().

Resources