By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,436 Members | 1,344 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,436 IT Pros & Developers. It's quick & easy.

enum { int_size_checked = 1/(sizeof(int)==4) };

P: n/a
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.
François Grieu
Dec 20 '06 #1
Share this Question
Share on Google+
5 Replies


P: n/a
On Wed, 20 Dec 2006 15:26:42 +0100, Francois Grieu wrote:
>Any better way to check the value of an expression
involving sizeof before runtime ?
http://www.embedded.com/showArticle....leID=164900888

Dec 20 '06 #2

P: n/a
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.

Dec 20 '06 #3

P: n/a
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.
Dec 21 '06 #4

P: n/a
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 ?
You might be able to achieve what you want with:

#include <limits.h>
#include <assert.h>

assert(CHAR_BIT == 8 && UINT_MAX == 0xffffffffu);

.... depending of course, on just exactly what it is that you want.

If the assertion is true, then sizeof(int) equals 4.
If the assertion is false,
then sizeof(int) may or may not equal 4.
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.
--
pete
Dec 21 '06 #5

P: n/a
Francois Grieu <fg****@gmail.comwrites:
Any better way to check the value of an expression
involving sizeof before runtime ?
switch (0) {
case 1:
case sizeof(int) != 4:
;
}

If sizeof(int) is not 4, then you'll get an error from a
duplicate case value.

Another possibility:
int dummy[sizeof(int) == 4 ? 1 : -1];
If sizeof(int) is not 4, the array ends up with an invalid size.

(Neither idea is original with me.)
--
"The lusers I know are so clueless, that if they were dipped in clue
musk and dropped in the middle of pack of horny clues, on clue prom
night during clue happy hour, they still couldn't get a clue."
--Michael Girdwood, in the monastery
Dec 21 '06 #6

This discussion thread is closed

Replies have been disabled for this discussion.