473,378 Members | 1,396 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Howto check value of constants in a macro

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
11 3003
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
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
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
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
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
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
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
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
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
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
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 thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

15
by: Bob | last post by:
I've tried everything; and I can't seem to get past this VERY (seemingly) simply problem. I want to work with an array variable within a function(s). I can't get it to work; if I: 1) global...
4
by: William Payne | last post by:
Hello, I am starting to steer away from the practice of using "using namespace std;" in my code. Instead I am qualifying each name in the source when I use them, for example: std::cout << "Hello";...
1
by: Benne Smith | last post by:
I can't seem to use my normal compiler constants from inside a macro ? It's possible to define NEW constants inside the macro, but this is not what i need. Does anybody know a way to get to...
2
by: Allan Ebdrup | last post by:
Hi I have two strings in memory, a XML document and a Schema, I would like a function that takes these two as parameters and returns an errordescription if the XML does not validate and an empty...
7
by: Don Wash | last post by:
Hi There! I'm trying to define constants so that I can refer those constants from any page of my ASP.NET website. I know I can use <appSettings> in web.config XML file but I don't want to parse...
1
by: Roy | last post by:
Hi, I have a problem that I have been working with for a while. I need to be able from server side (asp.net) to detect that the file i'm streaming down to the client is saved...
17
by: sounak | last post by:
How could we get a macro name from a macro value such that in a header file #define a 100 #define b 200 now the source file will be such that the user gives 100 then the value is outputted as...
29
by: Ancient_Hacker | last post by:
It sure would be nice if I could have a macro that add a level of indirection to its argument. So if I write: AddIndirection( X ) The macro AddIndirection will do: #define X (*X) ...
11
by: Bill Davy | last post by:
I am trying to edit Contacts in Outlook. This is so I can transfer numbers from my address book which is an Excel spreadsheet to my mobile phone. I came across the following snippet of code which...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.