#if sizeof...

K

Kenneth Brody

Is sizeof() legal within a #if preprocessor line?

Specifically, I would like to use the following "sanity check" at compile
time, but I'm getting an error on the compile about the #if line.

struct foo {
int a;
int b;
};

#if sizeof(struct foo) != 8
#pragma error "sizeof foo is not 8!"
#endif

(Assuming the "#pragma error" generates a compile-time error.)

Yes, I know all about the dangers and non-portability of things like this,
but it's in a low-level TCP/IP communications module, and I'd just like to
add a sanity check at compile time that I'm not on a platform where the
structs don't match the communications protocol.


--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
L

Lawrence Kirby

Is sizeof() legal within a #if preprocessor line?
No.

Specifically, I would like to use the following "sanity check" at compile
time, but I'm getting an error on the compile about the #if line.

struct foo {
int a;
int b;
};

#if sizeof(struct foo) != 8

Another problem would be that struct foo doesn't exist during
preprocessing phases.
#pragma error "sizeof foo is not 8!"
#endif

(Assuming the "#pragma error" generates a compile-time error.)

Yes, I know all about the dangers and non-portability of things like
this, but it's in a low-level TCP/IP communications module, and I'd just
like to add a sanity check at compile time that I'm not on a platform
where the structs don't match the communications protocol.

If you're expecting representation to match there are more issues than
just size.

Lawrence
 
R

Richard Tobin

Kenneth Brody said:
Is sizeof() legal within a #if preprocessor line?

No. The preprocessor doesn't know about such things.
I'd just like to
add a sanity check at compile time that I'm not on a platform where the
structs don't match the communications protocol.

There are various constructs that you could use to produce
compile-time errors if the size is wrong. For example:

char zzz[1 - 2*(sizeof(struct foo) != 8)];

But the error message will not be very enlightening.

-- Richard
 
S

S.Tobias

Richard Tobin said:
char zzz[1 - 2*(sizeof(struct foo) != 8)];

A very cute idea! I've stolen it, thank you!

#define CCASSERT(predicate) _x_CCASSERT_LINE(predicate, __LINE__)
[...]
#define _x_CCASSERT_LINE_CAT(predicate, line) \
typedef char constraint_violated_on_line_##line[2*((predicate)!=0)-1];

Due to typedef declaration no object is created, and the declaration
requires `predicate' to be a constant (scalar) expression. Another
equivalent possibility would be to replace "typedef" with "extern".
But the error message will not be very enlightening.

The message from gcc is enough informative:
constr.c:30: size of array `constraint_violated_on_line_30' is negative
 
K

Kenneth Brody

Lawrence said:

That's the conclusion I was coming to. Thanks.

[...]
If you're expecting representation to match there are more issues than
just size.

True. But, as I said, this was just a "sanity check", and "the odds
are" that if the size of the struct matches, the component pieces of
the struct align as expected. Obviously, further testing on a new
platform would be necessary to assure that this was the case.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
K

Kenneth Brody

S.Tobias said:
Richard Tobin said:
char zzz[1 - 2*(sizeof(struct foo) != 8)];

A very cute idea! I've stolen it, thank you!

ITYM "snarf". ;-)
#define CCASSERT(predicate) _x_CCASSERT_LINE(predicate, __LINE__)
[...]
#define _x_CCASSERT_LINE_CAT(predicate, line) \
typedef char constraint_violated_on_line_##line[2*((predicate)!=0)-1];

Due to typedef declaration no object is created, and the declaration
requires `predicate' to be a constant (scalar) expression. Another
equivalent possibility would be to replace "typedef" with "extern".
But the error message will not be very enlightening.

The message from gcc is enough informative:
constr.c:30: size of array `constraint_violated_on_line_30' is negative

Nice enhancement.

However, why did you switch "1 - 2*x" to "2*x - 1"?

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
N

Neil Kurzman

Kenneth said:
Is sizeof() legal within a #if preprocessor line?

Specifically, I would like to use the following "sanity check" at compile
time, but I'm getting an error on the compile about the #if line.

struct foo {
int a;
int b;
};

#if sizeof(struct foo) != 8
#pragma error "sizeof foo is not 8!"
#endif

(Assuming the "#pragma error" generates a compile-time error.)

Yes, I know all about the dangers and non-portability of things like this,
but it's in a low-level TCP/IP communications module, and I'd just like to
add a sanity check at compile time that I'm not on a platform where the
structs don't match the communications protocol.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>

limits.h has the size of all the variables. You should be able to use something
in there to get the size of int.
 
K

Keith Thompson

Neil Kurzman said:
Kenneth said:
Is sizeof() legal within a #if preprocessor line?

Specifically, I would like to use the following "sanity check" at compile
time, but I'm getting an error on the compile about the #if line.

struct foo {
int a;
int b;
};

#if sizeof(struct foo) != 8
#pragma error "sizeof foo is not 8!"
#endif

(Assuming the "#pragma error" generates a compile-time error.)
[...]

limits.h has the size of all the variables. You should be able to
use something in there to get the size of int.

<limits.h> has the bounds of the predefined integer types, not their
sizes. If there are padding bits, you can't reliably determine their
sizes from their bounds.

Also, that doesn't necessarily give you sizeof(struct foo). The
compiler could insert padding between a and b or after b. That's not
likely for a struct with just two int members (sizeof(struct foo) is
almost certainly equal to 2*sizeof(int)), but presumably the OP wants
to do this for more elaborate types.

Note that you can use assert() to force a run-time error. If the
program aborts immediately, that's almost as good as bombing at
compile time.
 
K

Keith Thompson

Kenneth Brody said:
#if sizeof(struct foo) != 8
#pragma error "sizeof foo is not 8!"
#endif

(Assuming the "#pragma error" generates a compile-time error.)

Just use "#error" rather than "#pragma error".
 
E

Emmanuel Delahaye

Kenneth Brody wrote on 14/01/05 :
Is sizeof() legal within a #if preprocessor line?

Not portably. A question of stage of translation. At this stage
(preprocessor), the standard says that sizeof is not yet evaluated and
returns 0.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
S

S.Tobias

Kenneth Brody said:
S.Tobias said:
char zzz[1 - 2*(sizeof(struct foo) != 8)];
#define CCASSERT(predicate) _x_CCASSERT_LINE(predicate, __LINE__)
[...]
#define _x_CCASSERT_LINE_CAT(predicate, line) \
typedef char constraint_violated_on_line_##line[2*((predicate)!=0)-1];
Nice enhancement.

....wasn't original either. :p
I had the idea when I remembered constraints classes in C++ (see Bjarne
Stroustrup's homepage; www.boost.org has a whole library of them).
However, why did you switch "1 - 2*x" to "2*x - 1"?

For no reason; I dont mind 1-2*((predicate)==0), I just want CCASSERT
to fail when `predicate' is false (ie. evaluates to zero or null pointer).
 
G

Giorgos Keramidas

Lawrence said:
Is sizeof() legal within a #if preprocessor line? [...]
Yes, I know all about the dangers and non-portability of things like
this, but it's in a low-level TCP/IP communications module, and I'd
just like to add a sanity check at compile time that I'm not on a
platform where the structs don't match the communications protocol.

If you're expecting representation to match there are more issues
than just size.

True. But, as I said, this was just a "sanity check", and "the odds
are" that if the size of the struct matches, the component pieces of
the struct align as expected.

That depends on what is 'expected'.

The alignment of fields and the total size of the struct may depend on
their order. On a platform with sizeof(short) = 2 && sizeof(int) == 4
&& sizeof(long) == 8 *and* unaligned access is prohibited by the
underlying hardware, the foo and bar structs shown below will have
different sizes if the compiler pads the struct members:

struct foo { struct bar {
short a; short a;
short b; int c;
int c; short b;
long d; long d;
}; };
 
G

Guest

S.Tobias said:
Richard Tobin said:
char zzz[1 - 2*(sizeof(struct foo) != 8)];

A very cute idea! I've stolen it, thank you!

#define CCASSERT(predicate) _x_CCASSERT_LINE(predicate, __LINE__)
[...]
#define _x_CCASSERT_LINE_CAT(predicate, line) \
typedef char constraint_violated_on_line_##line[2*((predicate)!=0)-1];

Due to typedef declaration no object is created, and the declaration
requires `predicate' to be a constant (scalar) expression. Another
equivalent possibility would be to replace "typedef" with "extern".
But the error message will not be very enlightening.

The message from gcc is enough informative:
constr.c:30: size of array `constraint_violated_on_line_30' is negative

'extern' is surely better than 'typedef' as the latter has the slight
but neck-breaking chance to end up on the same line in two different
header files or a header file is included twice, which stops
compilation with a illegal redefinition (or worse, silently switches
the compile run to C++). OTOH, I bet someone is working on an
implementation where the linker chokes on the missing definitions for
those externs.

Mark
 
G

Guest

S.Tobias said:
Richard Tobin said:
char zzz[1 - 2*(sizeof(struct foo) != 8)];

A very cute idea! I've stolen it, thank you!

#define CCASSERT(predicate) _x_CCASSERT_LINE(predicate, __LINE__)
[...]
#define _x_CCASSERT_LINE_CAT(predicate, line) \
typedef char constraint_violated_on_line_##line[2*((predicate)!=0)-1];

Due to typedef declaration no object is created, and the declaration
requires `predicate' to be a constant (scalar) expression. Another
equivalent possibility would be to replace "typedef" with "extern".
But the error message will not be very enlightening.

The message from gcc is enough informative:
constr.c:30: size of array `constraint_violated_on_line_30' is negative
s/[[:upper:]]//g`

'extern' is surely better than 'typedef' as the latter has the slight
but neck-breaking chance to end up on the same line in two different
header files or a header file is included twice, which stops
compilation with a illegal redefinition (or worse, silently switches
the compile run to C++). OTOH, I bet someone is working on an
implementation where the linker chokes on the missing definitions for
those externs.

Mark

Hmmm...I checked and only gcc refuses the compilation of two identical
typedefs, Metrowerks and Borland don't have a problem with them. I
wonder who violates the standard?

Mark
 
O

Old Wolf

Hmmm...I checked and only gcc refuses the compilation of two identical
typedefs, Metrowerks and Borland don't have a problem with them. I
wonder who violates the standard?

I don't know but it's really annoying. glibc defines
"typedef unsigned long ulong" depending on what other
switches you have #defined before including a system
header. Some other libraries define the same thing. I
define it in my own code too, for portability. I always
end up with a screenful of defines to ensure ulong is
defined once and only once. (Same goes for ushort, etc.)
I don't see what the problem is with having two identical
typedefs. (Same goes for a re-definition of a macro
to exactly the same thing as it was already defined to).
 
B

Ben Pfaff

Old Wolf said:
I don't know but it's really annoying. glibc defines
"typedef unsigned long ulong" depending on what other
switches you have #defined before including a system
header. Some other libraries define the same thing. I
define it in my own code too, for portability.

For portability? You mean, just in case your C compiler doesn't
support "unsigned long" directly?
 
K

Keith Thompson

Kenneth Brody said:
Is sizeof() legal within a #if preprocessor line?

No.

The definitive (and hilarious) statement on this was posted to
comp.std.c in 1998:

] > You are right. It was nice back in the days when things like
] >
] > #if (sizeof(int) == 8)
] >
] > actually worked (on some compilers).
]
] Must have been before my time.
]
] Dennis

Yes, that was Dennis Ritchie, inventor of C.

<http://groups-beta.google.com/group/comp.std.c/msg/4852afc61a060d89?dmode=source>
 
L

Lawrence Kirby

The C99 6.7p3 (constraints) says:

"If an identifier has no linkage, there shall be no more than one
declaration of the identifier (in a declarator or type specifier) with
the same scope and in the same name space, except for tags as specified
in 6.7.2.3."

So 2 identical typedefs at, say, file scope require a diagnostic. Maybe
Metrowerks and Borland need an option to make them conforming in this
respect.

Lawrence
 
K

Kenneth Brody

Keith said:
Kenneth Brody said:
Is sizeof() legal within a #if preprocessor line?

No.

The definitive (and hilarious) statement on this was posted to
comp.std.c in 1998:

] > You are right. It was nice back in the days when things like
] >
] > #if (sizeof(int) == 8)
] >
] > actually worked (on some compilers).
]
] Must have been before my time.
]
] Dennis

Yes, that was Dennis Ritchie, inventor of C.

<http://groups-beta.google.com/group/comp.std.c/msg/4852afc61a060d89?dmode=source>

Thanks for the chuckle.

Reminds me of the story regarding a conference where a speaker got into a
discussion regarding compatibility with the Korn shell, and it turned out
that the audience member he was arguing with was David Korn himself. (I
couldn't remember enough of the story to Google it.)

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

#if typedef() 10
Sorta-OT: John Backus obit 5
"(unsigned)" with long/int 10
YKYBRclcTLW 13
C wiki - struct tm 7
C FAQs section 20.27 9
Is "?" a sequence point? 7
Calling functions with the wrong parameters 7

Members online

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,123
Latest member
Layne6498
Top