I have been searching for an hour about this seemingly obvious question, and read several other posts including this one with the same title, but I am still struggling to find a convincing answer. Please forgive my ignorance in advance, and consider this code:
#define MY_MACRO 1
#define IMPLEMENT(x) (defined(x) && (x))
#if IMPLEMENT(MY_MACRO)
#define TESTVAL 1
#else
#define TESTVAL 0
#endif
#include <stdio.h>
int main()
{
printf("Value is %d\n", TESTVAL);
return 0;
}
Which doesn't compile and the error messages are:
error: operator "defined" requires an identifier
error: missing '(' in expression
One of the answers in the linked thread says the argument of IMPLEMENT is not known at compile-time, so we cannot use it with '#if defined'. But I don't think this is the case here. Can anyone explain why this doesn't compile?
Bonus question: is there any trick to safely replace the line #if defined(x) && x?
Can anyone explain why this doesn't compile?
IMPLEMENT(MY_MACRO) is expanding MY_MACRO to 1 and then replacing it for defined(1). defined(1) is invalid. 1 is not an identifier.
is there any trick to replace the line #if defined(x) && x?
Yes, just use #if x. If it's not defined, then it's zero. Just #if x, no need for a defined.
#if MY_MACRO
When I run the following code,
#include<stdio.h>
#define X (4+Y)
#define Y (X+3)
int main()
{
printf("%d",4*X+2);
return 0;
}
I am getting the following output:
Error: Undefined symbol 'X'
Can someone please explain the output?
It is because the macro expects and argument since its defined with parentheses.
You would need to define it as
#define X 4+Y and #define Y X+3. Then you would run into another trouble because of cyclic definition in macros.
To be even more correct, as Drew suggested; when the example would be compilable when defining macros one usually puts the parentheses around expression to ensure expected operator precedence.
So your best shot would be:
#define X (4+Y)
#define Y (X+3)
Very close to your initial example, just a space character between name of a macro and its definition. However, it is still impossible to properly expand the macro due to the cyclic reference.
How to check what happened:
You can use gcc -E, which outputs a pre-processed file. It generates lots of output so I used tail. I also used 2>err to redirect error stream to a file, so the output is clear.
luk32:~/projects/tests$ gcc -E ./cyclic_macro_with_no_spaces.c 2> err | tail -n 6
int main()
{
printf("%d",4*X+2);
return 0;
}
luk32:~/projects/tests$ gcc -E ./cyclic_macro.c 2> err | tail -n 6
int main()
{
printf("%d",4*(4+(X+3))+2);
return 0;
}
In 1st example the X did not expand at all. While in the latter both macros got expanded, although only one. Giving the same output that Geoffrey presented in his answer.
Whether no space is a typo or not there is an undefined symbol 'X'. For different reason that are possible to trace by analyzing err files.
If the macros are left as invalid function-like macros, they are not getting expanded at all because you did not call it with parentheses. So X is never replaced with anything by the pre-processor, and is the reason for the Undefined symbol 'X' in your sample code.
If you wanted this to be expanded you would have to call it with parentheses like this:
printf("%d",4*X()+2);
This though would just error out when pre-processed as 4+Y and X+3 are not valid macro parameter names.
If your answer is corrected somewhat so that those defines are proper defines, and not function-like macros, ie:
#define X (4+Y)
#define Y (X+3)
You have a circular reference between the defines...
X -> Y -> X... etc.
Since it will only expand the macro once, it is getting expanded to
printf("%d",4*(4+(X+3))+2);
This explains why X is the undefined symbol in this use case.
You miss spaces
#define X (4+Y)
#define Y (X+3)
#define SOUND_SPEED 0.034;
int rtt; //round trip time in microsecond
double distance;
distance = (double)(rtt*SOUND_SPEED)/2;
It complains error: expected expression before '/' token. Was is it bacause I can't use macro to define decimals or what?
Drop the semicolon:
#define SOUND_SPEED 0.034;
^
If you keep it the generated code will look like this:
distance = (double)(rtt*SOUND_SPEED;)/2;
^
#define SOUND_SPEED 0.034;
^
Do not use the trailing ;
Actually you should never terminate a macro with a ;:
PRE11-C. Do not conclude macro definitions with a semicolon
https://www.securecoding.cert.org/confluence/display/seccode/PRE11-C.+Do+not+conclude+macro+definitions+with+a+semicolon
You're using C, but you're trying to use a C++ style // comment. Depending on your compiler, that may not be allowed.
Edit: In fact, gcc -c89 -ansi gives that exact error message for a // comment and a totally different one for the extraneous ; in the define.
Is there any way to use a sizeof in a preprocessor macro?
For example, there have been a ton of situations over the years in which I wanted to do something like:
#if sizeof(someThing) != PAGE_SIZE
#error Data structure doesn't match page size
#endif
The exact thing I'm checking here is completely made up - the point is, I often like to put in these types of (size or alignment) compile-time checks to guard against someone modifying a data-structure which could misalign or re-size things which would break them.
Needless to say - I don't appear to be able to use a sizeof in the manner described above.
There are several ways of doing this.
Following snippets will produce no code if sizeof(someThing) equals PAGE_SIZE; otherwise they will produce a compile-time error.
1. C11 way
Starting with C11 you can use static_assert (requires #include <assert.h>).
Usage:
static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size");
2. Custom macro
If you just want to get a compile-time error when sizeof(something) is not what you expect, you can use following macro:
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
Usage:
BUILD_BUG_ON( sizeof(someThing) != PAGE_SIZE );
This article explains in details why it works.
3. MS-specific
On Microsoft C++ compiler you can use C_ASSERT macro (requires #include <windows.h>), which uses a trick similar to the one described in section 2.
Usage:
C_ASSERT(sizeof(someThing) == PAGE_SIZE);
Is there anyway to use a "sizeof" in a pre-processor macro?
No. The conditional directives take a restricted set of conditional expressions; sizeof is one of the things not allowed.
Preprocessing directives are evaluated before the source is parsed (at least conceptually), so there aren't any types or variables yet to get their size.
However, there are techniques to getting compile-time assertions in C (for example, see this page).
I know it's a late answer, but to add on to Mike's version, here's a version we use that doesn't allocate any memory. I didn't come up with the original size check, I found it on the internet years ago and unfortunately can't reference the author. The other two are just extensions of the same idea.
Because they are typedef's, nothing is allocated. With the __LINE__ in the name, it's always a different name so it can be copied and pasted where needed. This works in MS Visual Studio C compilers, and GCC Arm compilers. It does not work in CodeWarrior, CW complains about redefinition, not making use of the __LINE__ preprocessor construct.
//Check overall structure size
typedef char p__LINE__[ (sizeof(PARS) == 4184) ? 1 : -1];
//check 8 byte alignment for flash write or similar
typedef char p__LINE__[ ((sizeof(PARS) % 8) == 0) ? 1 : 1];
//check offset in structure to ensure a piece didn't move
typedef char p__LINE__[ (offsetof(PARS, SUB_PARS) == 912) ? 1 : -1];
I know this thread is really old but...
My solution:
extern char __CHECK__[1/!(<<EXPRESSION THAT SHOULD COME TO ZERO>>)];
As long as that expression equates to zero, it compiles fine. Anything else and it blows up right there. Because the variable is extern'd it will take up no space, and as long as no-one references it (which they won't) it won't cause a link error.
Not as flexible as the assert macro, but I couldn't get that to compile in my version of GCC and this will... and I think it will compile just about anywhere.
The existing answers just show how to achieve the effect of "compile-time assertions" based on the size of a type. That may meet the OP's needs in this particular case, but there are other cases where you really need a preprocessor conditional based on the size of a type. Here's how to do it:
Write yourself a little C program like:
/* you could call this sizeof_int.c if you like... */
#include <stdio.h>
/* 'int' is just an example, it could be any other type */
int main(void) { printf("%zd", sizeof(int); }
Compile that. Write a script in your favorite scripting language, which runs the above C program and captures its output. Use that output to generate a C header file. For example, if you were using Ruby, it might look like:
sizeof_int = `./sizeof_int`
File.open('include/sizes.h','w') { |f| f.write(<<HEADER) }
/* COMPUTER-GENERATED, DO NOT EDIT BY HAND! */
#define SIZEOF_INT #{sizeof_int}
/* others can go here... */
HEADER
Then add a rule to your Makefile or other build script, which will make it run the above script to build sizes.h.
Include sizes.h wherever you need to use preprocessor conditionals based on sizes.
Done!
(Have you ever typed ./configure && make to build a program? What configure scripts do is basically just like the above...)
What about next macro:
/*
* Simple compile time assertion.
* Example: CT_ASSERT(sizeof foo <= 16, foo_can_not_exceed_16_bytes);
*/
#define CT_ASSERT(exp, message_identifier) \
struct compile_time_assertion { \
char message_identifier : 8 + !(exp); \
}
For example in comment MSVC tells something like:
test.c(42) : error C2034: 'foo_can_not_exceed_16_bytes' : type of bit field too small for number of bits
Just as a reference for this discussion, I report that some compilers get sizeof() ar pre-processor time.
JamesMcNellis answer is correct, but some compilers go through this limitation (this probably violates strict ansi c).
As a case of this, I refer to IAR C-compiler (probably the leading one for professional microcontroller/embedded programming).
#define SIZEOF(x) ((char*)(&(x) + 1) - (char*)&(x)) might work
In C11 _Static_assert keyword is added. It can be used like:
_Static_assert(sizeof(someThing) == PAGE_SIZE, "Data structure doesn't match page size")
In my portable c++ code ( http://www.starmessagesoftware.com/cpcclibrary/ ) wanted to put a safe guard on the sizes of some of my structs or classes.
Instead of finding a way for the preprocessor to throw an error ( which cannot work with sizeof() as it is stated here ), I found a solution here that causes the compiler to throw an error.
http://www.barrgroup.com/Embedded-Systems/How-To/C-Fixed-Width-Integers-C99
I had to adapt that code to make it throw an error in my compiler (xcode):
static union
{
char int8_t_incorrect[sizeof( int8_t) == 1 ? 1: -1];
char uint8_t_incorrect[sizeof( uint8_t) == 1 ? 1: -1];
char int16_t_incorrect[sizeof( int16_t) == 2 ? 1: -1];
char uint16_t_incorrect[sizeof(uint16_t) == 2 ? 1: -1];
char int32_t_incorrect[sizeof( int32_t) == 4 ? 1: -1];
char uint32_t_incorrect[sizeof(uint32_t) == 4 ? 1: -1];
};
After trying out the mentioned macro's, this fragment seems to produce the desired result (t.h):
#include <sys/cdefs.h>
#define STATIC_ASSERT(condition) typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
STATIC_ASSERT(sizeof(int) == 4);
STATIC_ASSERT(sizeof(int) == 42);
Running cc -E t.h:
# 1 "t.h"
...
# 2 "t.h" 2
typedef char _static_assert_3[ (sizeof(int) == 4) ? 1 : -1];
typedef char _static_assert_4[ (sizeof(int) == 42) ? 1 : -1];
Running cc -o t.o t.h:
% cc -o t.o t.h
t.h:4:1: error: '_static_assert_4' declared as an array with a negative size
STATIC_ASSERT(sizeof(int) == 42);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
t.h:2:84: note: expanded from macro 'STATIC_ASSERT'
...typedef char __CONCAT(_static_assert_, __LINE__)[ (condition) ? 1 : -1]
^~~~~~~~~~~~~~~~~~~~
1 error generated.
42 isn't the answer to everything after all...
To check at compile time the size of data structures against their constraints I've used this trick.
#if defined(__GNUC__)
{ char c1[sizeof(x)-MAX_SIZEOF_X-1]; } // brakets limit c1's scope
#else
{ char c1[sizeof(x)-MAX_SIZEOF_X]; }
#endif
If x's size is greater or equal than it's limit MAX_SIZEOF_X, then the gcc wil complain with a 'size of array is too large' error. VC++ will issue either error C2148 ('total size of array must not exceed 0x7fffffff bytes') or C4266 'cannot allocate an array of constant size 0'.
The two definitions are needed because gcc will allow a zero-sized array to be defined this way (sizeof x - n).
The sizeof operator is not available for the preprocessor, but you can transfer sizeof to the compiler and check the condition in runtime:
#define elem_t double
#define compiler_size(x) sizeof(x)
elem_t n;
if (compiler_size(elem_t) == sizeof(int)) {
printf("%d",(int)n);
} else {
printf("%lf",(double)n);
}
I am new at C programming. I thought when you type something like #define Const 5000 that the compiler just replaces every instance of Const with 5000 at compile time. Is that wrong?
I try doing this in my code and I get a syntax error. Why can't i do this?
#define STEPS_PER_REV 12345
... in some function
if(CurrentPosition >= STEPS_PER_REV)
{
// do some stuff here
}
The compiler complains about the if statement with a syntax error that gives me no details.
the people in the comments are right. You almost definitely have a semicolon at the end of your #define. This means that your assignment becomes:
CURRENT_POSITION = 12345;;
(assuming that you HAD a semicolon at the end of the line...)
but your if becomes:
if(CurrentPosition >= 12345;)
which is of course invalid.
remember, #defines are NOT C code. They don't need semicolons.
Your code fragment is correct. #define is literally a string subsitution (with a bit more intelligence).
You can check what the preprocessor is doing in gcc by using the -E option, which will output the code after the pre-processor has run.
You are correct in that the C preprocessor will just replace STEPS_PER_REV with 12345. So your if statement looks fine, based on the code you provided.
To get to the bottom of this, could you please post your code and the actual contents of the error message.
You are right when you say that the compiler replaces every instance with the content of the macro. Check the type of CurrentPosition, probably the error is there.
Yes, but that should be a const, not a macro. You probably getting the wrong type in your comparison.
#define in c are macros, they are used by c preprocessor to replace them when they're found. For example in your source code the
**#define MAX_VALUE 500**
*if( reservations < **MAX_VALUE** )*
{
......
}
will be become into
*if( reservations < **500**)*
{
......
}
after preprocessing step. So that they could be used in boolean statetments in if sentences.