Constant macro parameters

R

Ricardo Gibert

How can I "force" a macro to accept integer constants or expressions whose value is determined during compilation? For example, if
we have:

#define TEST(X) blah blah with X

I want the macro to be used as

x += TEST(5);
y += TEST(3*7);

and not as

z += TEST(i);
z += TEST(i*3);

when I would prefer a compile time error.

Is this possible in C?
 
K

Kevin Easton

Ricardo Gibert said:
How can I "force" a macro to accept integer constants or expressions whose value is determined during compilation? For example, if
we have:

#define TEST(X) blah blah with X

I want the macro to be used as

x += TEST(5);
y += TEST(3*7);

and not as

z += TEST(i);
z += TEST(i*3);

when I would prefer a compile time error.

Is this possible in C?

Yes, in C89 (which is the standard of C currently implemented by
virtually all compilers).

#define TEST(X) ((void)sizeof(int [X]), X)

This requires a diagnostic from a conforming C89 compiler if X is not a
compile-time constant. For example:

$ gcc -Wall -ansi -pedantic foo.c -o foo
foo.c: In function `main':
foo.c:14: warning: ANSI C forbids variable-size array `type name'
foo.c:15: warning: ANSI C forbids variable-size array `type name'

Unfortunately, most compilers are by default non-conforming, and many of
them implement variable sized arrays as an extension, so they don't
issue this required diagnostic unless specifically asked to run in
conforming mode.

In addition, variable sized arrays are part of the newer C99 C Standard,
so this method also doesn't work on the few compilers that support it.

- Kevin.
 
S

Stephan Wilms

Hi,

You might exploit the rule that the expression for a "case" construct
must be an unsigned integer expression. I was thinking along these
lines:

#define TEST(X) {switch(1) { case X: ; }}

This is required to produce an error diagnostic for a non constant
integral case expression.
 
K

Kevin Easton

Stephan Wilms said:
Hi,

You might exploit the rule that the expression for a "case" construct
must be an unsigned integer expression. I was thinking along these
lines:

#define TEST(X) {switch(1) { case X: ; }}

This is required to produce an error diagnostic for a non constant
integral case expression.

The problem with that is that you can't include a switch statement in a
macro that is supposed to behave like an expression.

- Kevin.
 
S

Scott Fluhrer

Kevin Easton said:
Ricardo Gibert said:
How can I "force" a macro to accept integer constants or expressions whose value is determined during compilation? For example, if
we have:

#define TEST(X) blah blah with X

I want the macro to be used as

x += TEST(5);
y += TEST(3*7);

and not as

z += TEST(i);
z += TEST(i*3);

when I would prefer a compile time error.

Is this possible in C?

Yes, in C89 (which is the standard of C currently implemented by
virtually all compilers).

#define TEST(X) ((void)sizeof(int [X]), X)

This requires a diagnostic from a conforming C89 compiler if X is not a
compile-time constant. For example:

$ gcc -Wall -ansi -pedantic foo.c -o foo
foo.c: In function `main':
foo.c:14: warning: ANSI C forbids variable-size array `type name'
foo.c:15: warning: ANSI C forbids variable-size array `type name'

Unfortunately, most compilers are by default non-conforming, and many of
them implement variable sized arrays as an extension, so they don't
issue this required diagnostic unless specifically asked to run in
conforming mode.

In addition, variable sized arrays are part of the newer C99 C Standard,
so this method also doesn't work on the few compilers that support it.

How about

#define TEST(X) (sizeof (struct { int tag : (X) ? 1 : 2; } ), X )

I don't know of any compiler that supports variable sized bitfields.
 
R

Ricardo Gibert

Scott Fluhrer said:
Kevin Easton said:
Ricardo Gibert said:
How can I "force" a macro to accept integer constants or expressions whose value is determined during compilation? For example, if
we have:

#define TEST(X) blah blah with X

I want the macro to be used as

x += TEST(5);
y += TEST(3*7);

and not as

z += TEST(i);
z += TEST(i*3);

when I would prefer a compile time error.

Is this possible in C?

Yes, in C89 (which is the standard of C currently implemented by
virtually all compilers).

#define TEST(X) ((void)sizeof(int [X]), X)

This requires a diagnostic from a conforming C89 compiler if X is not a
compile-time constant. For example:

$ gcc -Wall -ansi -pedantic foo.c -o foo
foo.c: In function `main':
foo.c:14: warning: ANSI C forbids variable-size array `type name'
foo.c:15: warning: ANSI C forbids variable-size array `type name'

Unfortunately, most compilers are by default non-conforming, and many of
them implement variable sized arrays as an extension, so they don't
issue this required diagnostic unless specifically asked to run in
conforming mode.

In addition, variable sized arrays are part of the newer C99 C Standard,
so this method also doesn't work on the few compilers that support it.

How about

#define TEST(X) (sizeof (struct { int tag : (X) ? 1 : 2; } ), X )

This works! Thanks!

Ideally, a more appropriate error message would be preferable (I use mingw), but my attempts at incorporating the const keyword to
this end did not bear fruit. Good enough for gov't work!
 
D

Dave Thompson

Yes, in C89 (which is the standard of C currently implemented by
virtually all compilers).

#define TEST(X) ((void)sizeof(int [X]), X)
Don't actually need the cast, the left argument of the comma operator
is already a void context.
This requires a diagnostic from a conforming C89 compiler if X is not a
compile-time constant. For example: <snip gcc>
Unfortunately, most compilers are by default non-conforming, and many of
them implement variable sized arrays as an extension, so they don't
issue this required diagnostic unless specifically asked to run in
conforming mode.

In addition, variable sized arrays are part of the newer C99 C Standard,
so this method also doesn't work on the few compilers that support it.
In the latter case could make it sizeof(struct { int foo [X]; }).

But at least gcc (2.95.2) actually supports variable-bound arrays
within a struct, and not just at the end! Bleah -- how un-C-like!


- David.Thompson1 at worldnet.att.net
 

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

Members online

Forum statistics

Threads
474,079
Messages
2,570,574
Members
47,206
Latest member
Zenden

Latest Threads

Top