Re: checking constant conditions on compile time



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
esosman@xxxxxxxxxxxxxxxxxxx
.



Relevant Pages

  • Re: Address syntax
    ... [Given a function l_SYM_2Bthat returns a struct that contains ... Rule describes how array objects are treated in a value context: ... a pointer value, stripping off the "array N of" part. ... compiler has to pass a pointer anyway. ...
    (comp.lang.c)
  • Re: register attribute
    ... part of an element of a complex array in one subroutine ... > of struct and struct of array behind the scenes to get a higher ... struct of arrays would be faster given a compiler too simple ... SIMD transformation ...
    (comp.lang.fortran)
  • Re: komplexes Problem mit Funktionszeigern
    ... Die Funktion gibt einen struct "by value" zurueck und bei der ... am Borland Compiler, da der Microsoft Compiler ... Man kann Argumente fuer eine Funktion z.B auf dem Stack uebergeben. ... Das funktioniert natuerlich nur fuer "Basis Typen" die in ein Register passen. ...
    (de.comp.lang.c)
  • Re: What is wrong with this code?
    ... Uh, yeah, for me on this compiler, just a warning, I think. ... ridiculous contortions to avoid using a pointer to an ARRAY. ... The use of a global struct is another unnecessary design flaw. ... the extra precision. ...
    (comp.lang.c)
  • Re: derefrencing pointer to incomplete type
    ... /* Given an array of floating point numbers and the length of the ... struct _graph_vertex { ... If your compiler complains if you take away ... typedef struct _graph graph_type; ...
    (comp.lang.c)