christian.bau wrote:
Francois Grieu wrote:
>Does this reliably cause a compile-time error
when int is not 4 bytes ?
enum { int_size_checked = 1/(sizeof(int)==4) };
Any better way to check the value of an expression
involving sizeof before runtime ? I also have:
{
void check_foo_size(void);
if (sizeof(foo)!=120) check_foo_size();
}
but I can't be sure this one will NOT generate a link-time
error, and a name collision is hard to rule out.
Difficult. It is one thing what the C Standard says, and another thing
what your compiler does.
In C99, your enum would be an error if sizeof (int) != 4 (exactly as
you want); on C90 it might be undefined behavior; I am not hundred
percent sure. I used to use a macro that evaluates to
sizeof ("" == (sizeof (int) != 4))
If sizeof (int) == 4, we get sizeof ("" == 0). 0 is a null pointer
constant, comparing char* and a null pointer constant gives a result of
type int, and sizeof (...) compiles. If sizeof (int) != 4, we get
sizeof ("" == 1) which compares a pointer and an int, which is not
legal, so you get an error. Not, however, when you use gcc. It is a
warning...
Another approach:
switch (0) { case 0: case sizeof (int) == 4: ; }
If sizeof (int) != 4, you have to labels case 0: which is not allowed.
Just check that it doesn't produce any code.
We have four possible solutions:
1. enum { int_size_checked = 1/(sizeof(int)==SIZE) };
2. int foo;
{
void check_foo_size(void);
if (sizeof(foo)!=SIZE) check_foo_size();
}
3. sizeof ("" == (sizeof (int) != SIZE));
4. switch (0) { case 0: case sizeof (int) == SIZE: ; }
Where we can vary the value SIZE in each to test behaviour when correct
and not correct on any given compiler.
We should look at each solution with the following metrics:
1. Does it prevent compilation when size is wrong? (good)
2. Does it prevent compilation when size is right? (bad)
3. Does it only issue warnings when size wrong? (bad)
4. Does it issue warnings when size is right? (bad)
Solution 1:
lc: issues warning and error when size is wrong;
no warning or error when size is right
bcc32: issues warning only when size is wrong;
no warning or error when size is right
gcc: issues warning and error when size is wrong;
no warning or error when size is right
cl: issues error when size is wrong;
no warning or error when size is right
tcc: issues error when size is wrong;
no warning or error when size is right
So solution 1 works nicely on all 5 compilers tested.
Solution 2:
lc: issues error when size is wrong;
issues error when size is right
bcc32: issues warning and error when size is wrong;
issues warning and error when size is right
gcc: issues error when size is wrong;
no warning or error when size is right
cl: issues error when size is wrong;
issues error when size is right
tcc: issues error when size is wrong;
issues error when size is right
So solution 2 is unusable on all but one compiler. The reference to
check_foo_size remains and the linker trips up even when the size is
right. The only compiler which removes the reference to check_foo_size
is gcc.
Solution 3:
lc: issues error when size is wrong;
no warning or error when size is right
bcc32: issues 2 warnings when size is wrong;
issues 1 warning when size is right
gcc: issues warning when size is wrong;
no warning or error when size is right
cl: issues warning when size is wrong;
no warning or error when size is right
tcc: issues 2 warnings when size is wrong;
issues 1 warning when size is right
So solution 3 is unusable on all but one compiler. Only lc considers the
comparison of pointer and integer as an error worth stopping compilation
over. And two of the compilers, bcc32 and tcc issue warnings no matter
what the situation.
Solution 4:
lc: issues error when size is wrong;
no warning or error when size is right
bcc32: issues 1 warning and 3 errors when size is wrong;
no warning or error when size is right
gcc: issues 2 errors when size is wrong;
no warning or error when size is right
cl: issues error when size is wrong
no warning or error when size is right
tcc: issues error when size is wrong
no warning or error when size is right
So solution 4 works nicely on all 5 compilers tested.
All compilers were tested with no options specified. Additional options
that enable or disable warnings or turn warnings into errors will of
course change the results.
These are the full names and versions of the 5 compilers used:
Logiciels/Informatique lcc-win32 version 3.8. Compilation date: Sep 15
2006 13:56:00
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
gcc (GCC) 3.4.4 (cygming special) (gdc 0.12, using dmd 0.125)
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Turbo C Version 2.01 Copyright (c) 1987, 1988 Borland International
--
Simon.