Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > checking constant conditions on compile time

Reply
Thread Tools

checking constant conditions on compile time

 
 
Urs Thuermann
Guest
Posts: n/a
 
      03-27-2006
What is the most elegant way to check certain conditions at compile
time? I.e. I want a compile time error to be generated if for example
the size of a struct is not a multiple of 4 or if one struct is larger
than another struct, etc.

I think of something like

#define CHECK(expr) static int dummy[((expr) != 0) - 1]

CHECK(sizeof(struct foo) % 4 == 0);
CHECK(sizeof(struct foo) <= sizeof(struct bar));

The macro expands to an array definition with size -1 which causes a
compile error, if the expr is false, i.e. zero.

The unpleasant thing in this definition is that it pollutes the names
space with a file scope name and I can use it only once per file,
since otherwise the array is defined multiply. Second, using the
preprocessor #error with an appropriate message would be nicer, but
the preprocessor #if can't be used, since the preprocessor can't
evaluate the sizeof operator.

So, is there some other nice way to achieve what I am looking for?

urs
 
Reply With Quote
 
 
 
 
Richard G. Riley
Guest
Posts: n/a
 
      03-27-2006
On 2006-03-27, Urs Thuermann <> wrote:
> What is the most elegant way to check certain conditions at compile
> time? I.e. I want a compile time error to be generated if for example
> the size of a struct is not a multiple of 4 or if one struct is larger
> than another struct, etc.
>
> I think of something like
>
> #define CHECK(expr) static int dummy[((expr) != 0) - 1]
>
> CHECK(sizeof(struct foo) % 4 == 0);
> CHECK(sizeof(struct foo) <= sizeof(struct bar));
>
> The macro expands to an array definition with size -1 which causes a
> compile error, if the expr is false, i.e. zero.
>
> The unpleasant thing in this definition is that it pollutes the names
> space with a file scope name and I can use it only once per file,
> since otherwise the array is defined multiply. Second, using the
> preprocessor #error with an appropriate message would be nicer, but
> the preprocessor #if can't be used, since the preprocessor can't
> evaluate the sizeof operator.
>
> So, is there some other nice way to achieve what I am looking for?
>
> urs


I had a quick google up of this since I was wondering about something
to do with sizeof anyway : this thread might help you --

http://tinyurl.com/ktbnh

or

http://groups.google.de/groups?q=ccassert

and the thread entitled "How two check struct size at compile time"


--
Aspirat primo Fortuna labori.
 
Reply With Quote
 
 
 
 
Eric Sosman
Guest
Posts: n/a
 
      03-27-2006
Urs Thuermann wrote:

> What is the most elegant way to check certain conditions at compile
> time? I.e. I want a compile time error to be generated if for example
> the size of a struct is not a multiple of 4 or if one struct is larger
> than another struct, etc.
>
> I think of something like
>
> #define CHECK(expr) static int dummy[((expr) != 0) - 1]
>
> CHECK(sizeof(struct foo) % 4 == 0);
> CHECK(sizeof(struct foo) <= sizeof(struct bar));
>
> The macro expands to an array definition with size -1 which causes a
> compile error, if the expr is false, i.e. zero.
>
> The unpleasant thing in this definition is that it pollutes the names
> space with a file scope name and I can use it only once per file,
> since otherwise the array is defined multiply.


That's no problem as long as all the definitions
agree.

> Second, using the
> preprocessor #error with an appropriate message would be nicer, but
> the preprocessor #if can't be used, since the preprocessor can't
> evaluate the sizeof operator.
>
> So, is there some other nice way to achieve what I am looking for?


Perhaps you could exploit the `sizeof' operator to
provoke the same error without actually declaring a data
object. Off-hand I can't think of a way to do this at
file scope (I can't think of a way to write a declaration
or definition that's a no-op), but if CHECK is used inside
function blocks it can expand to an executable no-op, e.g.

#define CHECK(expr) sizeof(char[((expr) != 0) - 1])

I'd also suggest you arrange for the array size to be
negative rather than zero if the assertion fails. Some
compilers support "C-ish" modes that permit zero-length
arrays, and you'd like CHECK to fail even if the compiler
is being operated in such a mode.

However, my larger suggestion is that you take a step
back and reconsider why you need CHECK in the first place.
Both the examples you give (perhaps not coincidentally) give
evidence of dubious design and coding practices. Why do you
care whether sizeof(struct foo) is a multiple of four? Why
would sizeof(struct foo) > sizeof(struct bar) make trouble
for your program? If you're concerned about such things, it
seems likely that you're engaging in type-punning or that
you're trying to match externally-imposed formats. In either
case, it might be better to re-code in cleaner fashion than
to ask the compiler for an "all clear" on dodgy doings.

Long ago I was a fan of strewing the code with compiler
bombs. I used them to check conditions somewhat like those
you illustrate, and I used them to mark temporary hacks that
needed to be revisited before product release. (This was
after I tracked a performance bug down to a "temporary" hack
that had lain forgotten in the code through three releases...)
Eventually, though, I came to believe that the compiler is a
translator, not an enforcer of software engineering standards.

--
Eric Sosman
lid
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      03-27-2006
Urs Thuermann wrote:
>
> What is the most elegant way to check certain conditions at compile
> time? I.e. I want a compile time error to be generated if for example
> the size of a struct is not a multiple of 4 or if one struct is larger
> than another struct, etc.
>
> I think of something like
>
> #define CHECK(expr) static int dummy[((expr) != 0) - 1]
>
> CHECK(sizeof(struct foo) % 4 == 0);
> CHECK(sizeof(struct foo) <= sizeof(struct bar));
>
> The macro expands to an array definition with size -1 which causes a
> compile error, if the expr is false, i.e. zero.
>
> The unpleasant thing in this definition is that it pollutes the names
> space with a file scope name and I can use it only once per file,
> since otherwise the array is defined multiply. Second, using the
> preprocessor #error with an appropriate message would be nicer, but
> the preprocessor #if can't be used, since the preprocessor can't
> evaluate the sizeof operator.
>
> So, is there some other nice way to achieve what I am looking for?


The assert macro in <assert.h>

--
pete
 
Reply With Quote
 
pete
Guest
Posts: n/a
 
      03-27-2006
pete wrote:
>
> Urs Thuermann wrote:
> >
> > What is the most elegant way to check certain conditions at compile
> > time? I.e. I want a compile time error to be generated if for example
> > the size of a struct is not a multiple of 4 or if one struct is larger
> > than another struct, etc.
> >
> > I think of something like
> >
> > #define CHECK(expr) static int dummy[((expr) != 0) - 1]
> >
> > CHECK(sizeof(struct foo) % 4 == 0);
> > CHECK(sizeof(struct foo) <= sizeof(struct bar));
> >
> > The macro expands to an array definition with size -1 which causes a
> > compile error, if the expr is false, i.e. zero.
> >
> > The unpleasant thing in this definition is that it pollutes the names
> > space with a file scope name and I can use it only once per file,
> > since otherwise the array is defined multiply. Second, using the
> > preprocessor #error with an appropriate message would be nicer, but
> > the preprocessor #if can't be used, since the preprocessor can't
> > evaluate the sizeof operator.
> >
> > So, is there some other nice way to achieve what I am looking for?

>
> The assert macro in <assert.h>


Actually, that's for run time not compile time.

--
pete
 
Reply With Quote
 
Jordan Abel
Guest
Posts: n/a
 
      03-27-2006
On 2006-03-27, pete <> wrote:
> Urs Thuermann wrote:
>>
>> What is the most elegant way to check certain conditions at compile
>> time? I.e. I want a compile time error to be generated if for example
>> the size of a struct is not a multiple of 4 or if one struct is larger
>> than another struct, etc.
>>
>> I think of something like
>>
>> #define CHECK(expr) static int dummy[((expr) != 0) - 1]
>>
>> CHECK(sizeof(struct foo) % 4 == 0);
>> CHECK(sizeof(struct foo) <= sizeof(struct bar));
>>
>> The macro expands to an array definition with size -1 which causes a
>> compile error, if the expr is false, i.e. zero.


An array definition with size 0 is also a compile error. remove " - 1"
from the definition. Also see below.

>> The unpleasant thing in this definition is that it pollutes the names
>> space with a file scope name and I can use it only once per file,
>> since otherwise the array is defined multiply. Second, using the
>> preprocessor #error with an appropriate message would be nicer, but
>> the preprocessor #if can't be used, since the preprocessor can't
>> evaluate the sizeof operator.
>>
>> So, is there some other nice way to achieve what I am looking for?

>
> The assert macro in <assert.h>


That's a run-time assert. He wants to check properties of constant
expressions at compile-time. I believe what he came up with is similar
to the traditional solution, other than the fact that it doesn't work
(for the reason I pointed out)

How about
#define CHECK(expr) (void)((int(*)[(expr)!=0])0)
cast /* null pointer constant */ 0 into pointer to array (expr)!=0 of
int, then cast to void, discarding.
 
Reply With Quote
 
Chris Torek
Guest
Posts: n/a
 
      03-28-2006
[On building a "compile-time assert" macro]

In article <>
Jordan Abel <> wrote:
>An array definition with size 0 is also a compile error.


It is in Standard C. Unfortunately, GNUC is quite popular, and
arrays with size zero are fine in GNUC, so in practice one must
often come up with a trick that works in both Standard C *and* GNUC.
(Zero-size arrays are probably available in some other not-quite-C
languages as well.)

>How about
>#define CHECK(expr) (void)((int(*)[(expr)!=0])0)
>cast /* null pointer constant */ 0 into pointer to array (expr)!=0 of
>int, then cast to void, discarding.


The (expr)!=0 part converts to 0 (if expr is false) or 1 (if expr
is true), which works fine for Standard C (as noted above). To
make it work for both Standard C and not-quite-C, we can convert
1 to 1 and 0 to -1:

#define TRUE_PLUS1_FALSE_MINUS1(expr) ((((expr) != 0) * 2) - 1)
#define COMPILE_TIME_ASSERT(expr) \
(void)sizeof(char [TRUE_PLUS1_FALSE_MINUS1(expr)])

or similar.

Note that both your CHECK and my COMPILE_TIME_ASSERT have to
be put in the "code" part of a program (inside a block, and
after the declarations in C89). There is a variant that can
appear only where declarations can go:

#define COMPILE_TIME_ASSERT_WITH_NAME(expr, name) \
typedef char name[TRUE_PLUS1_FALSE_MINUS1(expr)]

which is probably most useful with a few auxiliary macros to
generate an assertion-name based on source line number:

#define CONCAT(x, y) x ## y
#define CONCAT_EXPANSION(x, y) CONCAT(x, y)
#define COMPILE_TIME_ASSERT_2(expr) \
COMPILE_TIME_ASSERT_WITH_NAME(expr, CONCAT_EXPANSION(ASSERT, __LINE__))

Of course, you can only put one COMPILE_TIME_ASSERT_2() invocation
on any logical source line ("logical" meaning "after physical lines
are joined via backslash-newline splicing"). Thus:

COMPILE_TIME_ASSERT_2(sizeof(int) == \
sizeof(long)); COMPILE_TIME_ASSERT_2(CHAR_MAX == 127);

is bad for several reasons.
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
 
Reply With Quote
 
Urs Thuermann
Guest
Posts: n/a
 
      03-30-2006
Eric Sosman <> writes:

> but if CHECK is used inside
> function blocks it can expand to an executable no-op, e.g.
>
> #define CHECK(expr) sizeof(char[((expr) != 0) - 1])


OK, but I prefer to do at file scope, i.e. outside of any block. The
typedef suggested in this thread will do this.

> I'd also suggest you arrange for the array size to be
> negative rather than zero if the assertion fails.


I have actually written the macro so it makes the array size negative
if the assertion fails. But I should you positive instead of null
value, when the assertion holds, since [0] seems to be invalid, too.
I thought, it is allowed.

> However, my larger suggestion is that you take a step
> back and reconsider why you need CHECK in the first place.
> Both the examples you give (perhaps not coincidentally) give
> evidence of dubious design and coding practices. Why do you
> care whether sizeof(struct foo) is a multiple of four? Why
> would sizeof(struct foo) > sizeof(struct bar) make trouble
> for your program?


The check for multiple of 4 is something I needed 10+ years ago. I
memcpy()ed the struct to some memory block which was the input to a
compression algortihm that operated on 4-byte-values. I could do it
then, because the use compiler allowed siyeof() to be evaluated in the
C preprocessor. Today I would probably doit it in another way.

The other example comes from implementation of a new communication
protocol family, where I use a struct defined in some existing source
code I cannot change. The struct contains a union to hold data for a
number of already implemented protocols. My new protocol should use
the space of this union, too, but I ust ensure, that the struct for my
new protocol is not larger than the union.

urs
 
Reply With Quote
 
Urs Thuermann
Guest
Posts: n/a
 
      03-30-2006
Chris Torek <> writes:

> #define COMPILE_TIME_ASSERT_WITH_NAME(expr, name) \
> typedef char name[TRUE_PLUS1_FALSE_MINUS1(expr)]


Ah, the typedef is also nice, so not to create unused objects. Thanks
to all who have answered, to refine my first approach.


urs
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      03-30-2006
Urs Thuermann <> writes:
[...]
> The check for multiple of 4 is something I needed 10+ years ago. I
> memcpy()ed the struct to some memory block which was the input to a
> compression algortihm that operated on 4-byte-values. I could do it
> then, because the use compiler allowed siyeof() to be evaluated in the
> C preprocessor. Today I would probably doit it in another way.

[...]

What C compiler allowed sizeof to be evaluated in the preprocessor?

<http://groups.google.com/group/comp.std.c/msg/4852afc61a060d89?hl=en&>

--
Keith Thompson (The_Other_Keith) kst- <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
computation at compile time i.e. compile time functions usingtemplates Carter C++ 2 03-04-2009 06:43 PM
cant compile on linux system.cant compile on cant compile onlinux system. Nagaraj C++ 1 03-01-2007 11:18 AM
non static compile time constant .vs. static in tomcat ptg_abhishek@yahoo.com Java 1 11-17-2005 11:35 AM
Checking for race conditions with Ruby threads Wilson Bilkovich Ruby 0 11-08-2005 06:52 PM
Compile-time constant quiet NaN (double) ??? Lionel B C++ 6 05-14-2004 03:06 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57