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

Howto check value of constants in a macro

P: n/a
Hi,

I'd like to define several constants and make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro. Something like this:

#define MAX 999

#define DEF_CHECKED_VAL( name, value) #if (value < MAX) \
#define name MAX \
#else \
#define name value \
#endif

So
DEF_CHECKED_VAL(test_1, 33) should expand to #define test_1 33
and
DEF_CHECKED_VAL(test_2, 1000) should yield #define test_2 999
As you probably know (and I learned today) this doesn't work. The most
relevant FAQ to this problems seems to be "10.25 I've got this tricky
preprocessing I want to do and I can't figure out a way to do it."
Unfortunately writing my own preprocessor isn't really an option and I
can't believe that I'm the first one who'd like to implement this
functionality. Is there a well-known solution to my problem, or am I doing
something fundamentally stupid?

Thanks for any help, Rick
Nov 23 '05 #1
Share this Question
Share on Google+
11 Replies


P: n/a
Richard Meister <r.*******@t-online.de> writes:
I'd like to define several constants and make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro. Something like this:

#define MAX 999

#define DEF_CHECKED_VAL( name, value) #if (value < MAX) \
#define name MAX \
#else \
#define name value \
#endif

So
DEF_CHECKED_VAL(test_1, 33) should expand to #define test_1 33
and
DEF_CHECKED_VAL(test_2, 1000) should yield #define test_2 999


I think the #if logic above is opposite your examples, so that
the < should be >.

Here is one possible solution:
#define DEF_CHECKED_VAL(name, value) \
enum { name = (value) < MAX ? (value) : MAX };
--
int main(void){char p[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuv wxyz.\
\n",*q="kl BIcNBFr.NKEzjwCIxNJC";int i=sizeof p/2;char *strchr();int putchar(\
);while(*q){i+=strchr(p,*q++)-p;if(i>=(int)sizeof p)i-=sizeof p-1;putchar(p[i]\
);}return 0;}
Nov 23 '05 #2

P: n/a
Ben Pfaff <bl*@cs.stanford.edu> writes:
Richard Meister <r.*******@t-online.de> writes:
I'd like to define several constants and make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro. Something like this:

#define MAX 999

#define DEF_CHECKED_VAL( name, value) #if (value < MAX) \
#define name MAX \
#else \
#define name value \
#endif

So
DEF_CHECKED_VAL(test_1, 33) should expand to #define test_1 33
and
DEF_CHECKED_VAL(test_2, 1000) should yield #define test_2 999


I think the #if logic above is opposite your examples, so that
the < should be >.

Here is one possible solution:
#define DEF_CHECKED_VAL(name, value) \
enum { name = (value) < MAX ? (value) : MAX };


Oooh, that's clever!

If you need something more complex, that can't be expressed with
integer values and constant expressions, you can always implement your
own *simple* preprocessor. There's no need to write a fully
functional C preprocessor, just a program that produces C code as its
output.

For example, given an input like this:

MAX 999
DEF_CHECKED_VAL test_1 33
DEF_CHECKED_VAL test_2 1000

the program could produce the following output:

#define test_1 33
#define test_2 999

In your build procedure, you can run your program and generate a
header file that's then #included by your C source files. Define
whatever syntax and semantics you like for the tranformation; the
simpler it is, the easier it will be to implement.

(Personally, I'd use Perl for something like this, but it can
certainly be done in C.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <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.
Nov 23 '05 #3

P: n/a
Richard Meister wrote:

Hi,

I'd like to define several constants and
make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro.


I use the assert macro for that.

#include <assert.h>

void assert(scalar expression);

--
pete
Nov 23 '05 #4

P: n/a
Ben Pfaff wrote
(in article <87************@benpfaff.org>):
Richard Meister <r.*******@t-online.de> writes:
I'd like to define several constants and make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro. Something like this:

#define MAX 999

#define DEF_CHECKED_VAL( name, value) #if (value < MAX) \
#define name MAX \
#else \
#define name value \
#endif

So
DEF_CHECKED_VAL(test_1, 33) should expand to #define test_1 33
and
DEF_CHECKED_VAL(test_2, 1000) should yield #define test_2 999


I think the #if logic above is opposite your examples, so that
the < should be >.

Here is one possible solution:
#define DEF_CHECKED_VAL(name, value) \
enum { name = (value) < MAX ? (value) : MAX };


Wow, that is cool. I didn't think it would really work on first
look. :-)
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Nov 23 '05 #5

P: n/a
Keith Thompson <ks***@mib.org> writes:
If you need something more complex, that can't be expressed with
integer values and constant expressions, you can always implement your
own *simple* preprocessor. There's no need to write a fully
functional C preprocessor, just a program that produces C code as its
output.

For example, given an input like this:

MAX 999
DEF_CHECKED_VAL test_1 33
DEF_CHECKED_VAL test_2 1000

the program could produce the following output:

#define test_1 33
#define test_2 999


Even simpler is to write a C program that takes no input to do
it. For example (untested, not compiled, etc.):

#include <stdio.h>

int main (void) {
const int max = 999;

static const struct {
const char *name;
int value;
} *p, values[] = {
{"test_1", 33},
{"test_2", 1000},
};

int n_values = sizeof values / sizeof *values;

for (p = values; p < &values[n_values]; p++) {
int clamped_value = p->value < max ? p->value : max;
printf ("#define %s %d\n", p->name, clamped_value);
}
return 0;
}
--
"I hope, some day, to learn to read.
It seems to be even harder than writing."
--Richard Heathfield
Nov 23 '05 #6

P: n/a
In article <43***********@mindspring.com>,
pete <pf*****@mindspring.com> wrote:
Richard Meister wrote:

Hi,

I'd like to define several constants and
make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro.


I use the assert macro for that.

#include <assert.h>

void assert(scalar expression);


If you want to check at compile time, proceed as follows:

0 is a "null pointer constant", and 1 isn't.

Therefore "" == 0 is a valid expression and "" == 1 isn't.

Also, sizeof ("" == 0) is a valid expression and sizeof ("" == 1) isn't.
If you have two constants a and b, then ! (a < b) has a value of 0 if a
< b is true and a value of 1 if a < b is false.

sizeof ("" == ! (a < b)) is a valid expression if a < b and it is not a
valid expression if a >= b.

So if you have for example ten constants c0, c1, ..., 9 and you want to
check at compile time that each is less than 10, then all you need to do
is to write a function

static void compiletimechecks (void) {
sizeof ("" == ! (c0 < 10));
sizeof ("" == ! (c1 < 10));
...
sizeof ("" == ! (c9 < 10));
}

Suitable macros could make this more readable.
Nov 23 '05 #7

P: n/a
Christian Bau wrote:
In article <43***********@mindspring.com>,
pete <pf*****@mindspring.com> wrote:

Richard Meister wrote:
Hi,

I'd like to define several constants and
make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro.


I use the assert macro for that.

#include <assert.h>

void assert(scalar expression);

If you want to check at compile time, proceed as follows:

0 is a "null pointer constant", and 1 isn't.

Therefore "" == 0 is a valid expression and "" == 1 isn't.

Also, sizeof ("" == 0) is a valid expression and sizeof ("" == 1) isn't.
If you have two constants a and b, then ! (a < b) has a value of 0 if a
< b is true and a value of 1 if a < b is false.

sizeof ("" == ! (a < b)) is a valid expression if a < b and it is not a
valid expression if a >= b.

So if you have for example ten constants c0, c1, ..., 9 and you want to
check at compile time that each is less than 10, then all you need to do
is to write a function

static void compiletimechecks (void) {
sizeof ("" == ! (c0 < 10));
sizeof ("" == ! (c1 < 10));
...
sizeof ("" == ! (c9 < 10));
}

Suitable macros could make this more readable.


Shiny.
However, I like the
static char test_c0[10-c0];
trick (seen some time ago in clc) as well.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 23 '05 #8

P: n/a
In article <3u*************@individual.net>,
Michael Mair <Mi**********@invalid.invalid> wrote:
Christian Bau wrote:
In article <43***********@mindspring.com>,
pete <pf*****@mindspring.com> wrote:

Richard Meister wrote:

Hi,

I'd like to define several constants and
make sure that all of them are
smaller than a given other constant. I thought this could be done by a
simple macro.

I use the assert macro for that.

#include <assert.h>

void assert(scalar expression);

If you want to check at compile time, proceed as follows:

0 is a "null pointer constant", and 1 isn't.

Therefore "" == 0 is a valid expression and "" == 1 isn't.

Also, sizeof ("" == 0) is a valid expression and sizeof ("" == 1) isn't.
If you have two constants a and b, then ! (a < b) has a value of 0 if a
< b is true and a value of 1 if a < b is false.

sizeof ("" == ! (a < b)) is a valid expression if a < b and it is not a
valid expression if a >= b.

So if you have for example ten constants c0, c1, ..., 9 and you want to
check at compile time that each is less than 10, then all you need to do
is to write a function

static void compiletimechecks (void) {
sizeof ("" == ! (c0 < 10));
sizeof ("" == ! (c1 < 10));
...
sizeof ("" == ! (c9 < 10));
}

Suitable macros could make this more readable.


Shiny.
However, I like the
static char test_c0[10-c0];
trick (seen some time ago in clc) as well.


That has two problems: You can run into problems when c0 is unsigned
(for example c0 is 11u, 10 - 11u might be 65535u, and you might allocate
a static array of 65535 characters without warning! Second, you will
declare one or more static arrays and have to hope that compiler and
linker optimise them away. The function above is equivalent to

static void compiletimechecks (void) {
sizeof (int);
sizeof (int);
...
sizeof (int);
}

if it compiles at all and hopefully doesn't generate any code.
Nov 23 '05 #9

P: n/a
Keith Thompson <ks***@mib.org> wrote:
Ben Pfaff <bl*@cs.stanford.edu> writes:
Richard Meister <r.*******@t-online.de> writes: ....
#define MAX 999

#define DEF_CHECKED_VAL( name, value) #if (value < MAX) \
#define name MAX \
#else \
#define name value \
#endif

So
DEF_CHECKED_VAL(test_1, 33) should expand to #define test_1 33
and
DEF_CHECKED_VAL(test_2, 1000) should yield #define test_2 999


I think the #if logic above is opposite your examples, so that
the < should be >.

Here is one possible solution:
#define DEF_CHECKED_VAL(name, value) \
enum { name = (value) < MAX ? (value) : MAX };


Oooh, that's clever!


To expand on the method...
I think it's okay when we need just a number, but it won't work
for the situation where we require a constant of a specific type.
Would these always work as intended:
DEF_CHECKED_VAL(test_1, 33u)
DEF_CHECKED_VAL(test_2, 33l)
?

Also, obviously, enum members could not be used in pp directives:
DEF_CHECKED_VAL(test_1, 33)
/*...*/
#if test_1 > 32
My answer to the problem would rather be a simple:
#define MY_MAX 999
#define CK_MY_MAX(x) ((x) < MY_MAX ? (x) : MY_MAX)
#define test_1 CK_MY_MAX(33)
#define test_2 CK_MY_MAX(1000)
There's only one more word to type per each define. It produces
constant expressions, suitable for pp. Is there a situation where
constant integer expression could not be substituted for an integer
constant? (I don't think so.)

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 23 '05 #10

P: n/a
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
In article <3u*************@individual.net>,
Michael Mair <Mi**********@invalid.invalid> wrote:
Christian Bau wrote:
> If you want to check at compile time, proceed as follows:
>
> 0 is a "null pointer constant", and 1 isn't.
>
> Therefore "" == 0 is a valid expression and "" == 1 isn't.
>
> Also, sizeof ("" == 0) is a valid expression and sizeof ("" == 1) isn't.
>
>
> If you have two constants a and b, then ! (a < b) has a value of 0 if a
> < b is true and a value of 1 if a < b is false.
>
> sizeof ("" == ! (a < b)) is a valid expression if a < b and it is not a
> valid expression if a >= b.
>
> So if you have for example ten constants c0, c1, ..., 9 and you want to
> check at compile time that each is less than 10, then all you need to do
> is to write a function
>
> static void compiletimechecks (void) {
> sizeof ("" == ! (c0 < 10));
> sizeof ("" == ! (c1 < 10));
> ...
> sizeof ("" == ! (c9 < 10));
Why do we need `sizeof'? Wouldn't this be just enough:
"" == ! (c0 < 10);
?
(Actually, I'd probably add the cast:
(void)("" == ! (c0 < 10));
in order to suppress "code has no effect" warnings.)
> }
>
> Suitable macros could make this more readable.
Shiny.
However, I like the
static char test_c0[10-c0];
trick (seen some time ago in clc) as well.


In addtion to what Christian has already written (below), gcc accepts
char array[0];
(perhaps not in `-ansi' mode, but we need something practical).
That's why I have always coded this like:
static char test_c0[(c0 < 10) * 2 - 1];
(which has more chances to fail on any compiler if `c0' is not right).
Christian's method might be better, but I havn't checked it yet (I don't
want just warnings, I want the whole compiler to bail out).
That has two problems: You can run into problems when c0 is unsigned
(for example c0 is 11u, 10 - 11u might be 65535u, and you might allocate
a static array of 65535 characters without warning! Second, you will
declare one or more static arrays and have to hope that compiler and
linker optimise them away. The function above is equivalent to

[snip]

--
Stan Tobias
mailx `echo si***@FamOuS.BedBuG.pAlS.INVALID | sed s/[[:upper:]]//g`
Nov 23 '05 #11

P: n/a
S.Tobias wrote:
Christian Bau <ch***********@cbau.freeserve.co.uk> wrote:
In article <3u*************@individual.net>,
Michael Mair <Mi**********@invalid.invalid> wrote:
Christian Bau wrote:

If you want to check at compile time, proceed as follows:

0 is a "null pointer constant", and 1 isn't.

Therefore "" == 0 is a valid expression and "" == 1 isn't.

Also, sizeof ("" == 0) is a valid expression and sizeof ("" == 1) isn't.
If you have two constants a and b, then ! (a < b) has a value of 0 if a
< b is true and a value of 1 if a < b is false.

sizeof ("" == ! (a < b)) is a valid expression if a < b and it is not a
valid expression if a >= b.

So if you have for example ten constants c0, c1, ..., 9 and you want to
check at compile time that each is less than 10, then all you need to do
is to write a function

static void compiletimechecks (void) {
sizeof ("" == ! (c0 < 10));
sizeof ("" == ! (c1 < 10));
...
sizeof ("" == ! (c9 < 10));
Why do we need `sizeof'? Wouldn't this be just enough:
"" == ! (c0 < 10);
?
(Actually, I'd probably add the cast:
(void)("" == ! (c0 < 10));
in order to suppress "code has no effect" warnings.)
Hmmm, I'd say because even if the compiler does not
optimise at all,
sizeof ("" == ! (c0 < 10));
will give you
sizeof 0;
if the thing compiles (sprinkle with (void) ad libitum).
However,
"" == !(c0 < 10);
might be carried out otherwise, including memory for each
and every "".

It certainly is unnecessary for every C compiler I worked
with or generated code for, though.
}

Suitable macros could make this more readable.

Shiny.
However, I like the
static char test_c0[10-c0];
trick (seen some time ago in clc) as well.

In addtion to what Christian has already written (below), gcc accepts
char array[0];
(perhaps not in `-ansi' mode, but we need something practical).
That's why I have always coded this like:
static char test_c0[(c0 < 10) * 2 - 1];
(which has more chances to fail on any compiler if `c0' is not right).


Good one :-)
Christian's method might be better, but I havn't checked it yet (I don't
want just warnings, I want the whole compiler to bail out).


It certainly is more elegant.

That has two problems: You can run into problems when c0 is unsigned
(for example c0 is 11u, 10 - 11u might be 65535u, and you might allocate
a static array of 65535 characters without warning! Second, you will
declare one or more static arrays and have to hope that compiler and
linker optimise them away. The function above is equivalent to


True; your solution is better and safer to use in this respect. I only
used this for checking exact values (by using a pair of these arrays)
at compile time with appropriate casting.
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Nov 23 '05 #12

This discussion thread is closed

Replies have been disabled for this discussion.