#define VS regular variable?

0 views
Skip to first unread message

ava...@pride.hofstra.spam.edu

unread,
Feb 11, 2003, 8:47:48 PM2/11/03
to
Again, another question from the baby in the group, but I have to know.

What's the benefit of using #define for variables as opposed to defining
a variable in main?

Sorry for being so ignorant but I haven't found the reasoning behind
this anywhere I've looked yet.

Thanks,
A.V.

Ben Pfaff

unread,
Feb 11, 2003, 9:36:30 PM2/11/03
to
ava...@pride.hofstra.spam.edu writes:

> Again, another question from the baby in the group, but I have to know.
>
> What's the benefit of using #define for variables as opposed to
> defining a variable in main?

#define doesn't declare a variable. It declares a macro. You
can't assign to a macro, so it's not useful as a variable.

Jens.T...@physik.fu-berlin.de

unread,
Feb 11, 2003, 10:10:23 PM2/11/03
to

I guess you meant things like

#define LINE_LENGTH 512

LINE_LENGTH is not a variable but from now one everywhere the compiler
finds LINE_LENGTH in your code it will replace it by 512. That's quite
handy when you have certain fixed sizes in your program (like line
lengths, buffer sizes etc.) which you may want to change at some later
time without having to go through your whole program, replacing all
occurrences of 512 and possibly worrying if the 512 in a certain place
stands for the line length or e.g. a completely unrelated buffer size.

Using such macros also has the advantage that it can make programs a
lot easier to understand. When you see a line like

for ( i = 0; i < 512; i++ )

you can't immediately guess what this is going to be used for. But
with

for ( i = 0; i < LINE_LENGTH; i++ )

you will have at least a basic idea what's probably going on in this
loop.

You can also use macros with arguments (which make them look like
function calls), but as long as you're still fighting with the basics
you should avoid them, they can bite back in unexpected ways.

Regards, Jens
--
_ _____ _____
| ||_ _||_ _| Jens.T...@physik.fu-berlin.de
_ | | | | | |
| |_| | | | | | http://www.physik.fu-berlin.de/~toerring
\___/ens|_|homs|_|oerring

E. Gibbons

unread,
Feb 11, 2003, 11:02:37 PM2/11/03
to
In article <878ywm5...@pfaff.Stanford.EDU>,

Sure, you can assign to a macro:

#include <stdio.h>

#define X x

int main(void)
{
int x;

X = 42; /* look, ma, I'm assigning to a macro! */
printf("%d %d\n", x, X);
return 0;
}

Whether X is "useful" as a variable is debateable in this trivial case,
but it certainly *behaves* like a variable.

Of course, the OP probably meant what's the benefit of using #define
for *constants*, which is a different matter.

--Ben
--

Ben Pfaff

unread,
Feb 11, 2003, 11:23:25 PM2/11/03
to
euph...@u.washington.edu (E. Gibbons) writes:

> In article <878ywm5...@pfaff.Stanford.EDU>,
> Ben Pfaff <b...@cs.stanford.edu> wrote:
> >ava...@pride.hofstra.spam.edu writes:
> >
> >> Again, another question from the baby in the group, but I have to know.
> >>
> >> What's the benefit of using #define for variables as opposed to
> >> defining a variable in main?
> >
> >#define doesn't declare a variable. It declares a macro. You
> >can't assign to a macro, so it's not useful as a variable.
>
> Sure, you can assign to a macro:
>
> #include <stdio.h>
>
> #define X x
>
> int main(void)
> {
> int x;
>
> X = 42; /* look, ma, I'm assigning to a macro! */
> printf("%d %d\n", x, X);
> return 0;
> }

Looks to me like you just assigned to a variable.
--
"In My Egotistical Opinion, most people's C programs should be indented six
feet downward and covered with dirt." -- Blair P. Houghton

nrk

unread,
Feb 11, 2003, 11:27:40 PM2/11/03
to
ava...@pride.hofstra.spam.edu wrote:

#defines are not used to define variables. They are typically used to
define constants (aka magic numbers) that are used in your programs. For
instance, let's say you are building an editor where you arbitrarily set an
upper limit on the length of a line to be 512 characters. Instead of
hardcoding the magic number 512 everywhere in your program where you need
the maximum line length, you can do the following:

#define MAX_LINELEN 512

and then use MAX_LINELEN instead of 512 wherever you need the value of the
max. line length. Advantage? Say tomorrow you want to increase the max.
line length to 1024, in theory just changing the #define to:

#define MAX_LINELEN 1024

will magically effect this change all across your code (in practice though,
due to human frailities it's rarely so easy).

Note that this is just one use of the #define mechanism. There are several
other possible (ab)uses.

-nrk.

ava...@pride.hofstra.spam.edu

unread,
Feb 12, 2003, 3:44:15 AM2/12/03
to

Sure, I understand the idea behind a global variable, so I guess the
question is if I'm only using the define as a global variable, is there
any benefit over simply assigning a global variable in the main() of a
program?

Is it even possible in C to delcare a variable as global? I guess I'm
assuming that, maybe I shouldn't be.

Thanks for all the insight,
A.V.

Kevin Easton

unread,
Feb 12, 2003, 4:57:56 AM2/12/03
to
ava...@pride.hofstra.spam.edu wrote:
[snip]

> Sure, I understand the idea behind a global variable, so I guess the
> question is if I'm only using the define as a global variable, is there
> any benefit over simply assigning a global variable in the main() of a
> program?

#define'd constants can be "manifest constants" - you can use them in
places you can't use a variable (even a const- qualified one), like in
array sizes.

> Is it even possible in C to delcare a variable as global? I guess I'm
> assuming that, maybe I shouldn't be.

Depends on what you mean. A variable at file scope is visible anywhere
in that file after the point it's declared, as long as it's not hidden
by another identifier with the same name in an inner scope. Such a
variable with external linkage can be accessed from any module in your
complete program.

- Kevin.

Joona I Palaste

unread,
Feb 12, 2003, 6:14:25 AM2/12/03
to
Kevin Easton <ke...@pcug.org.au> scribbled the following:

> ava...@pride.hofstra.spam.edu wrote:
> [snip]
>> Sure, I understand the idea behind a global variable, so I guess the
>> question is if I'm only using the define as a global variable, is there
>> any benefit over simply assigning a global variable in the main() of a
>> program?

> #define'd constants can be "manifest constants" - you can use them in
> places you can't use a variable (even a const- qualified one), like in
> array sizes.

This is because #define'd constants behave differently from
variables. Variables hold values, #define'd constans ARE their values.
The compiler won't be able to tell a #define'd constant from a
literal value.
This also means that you lose all the benefits of having a variable -
such as being able to reassign it, or having an address, or simply even
having a type.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"I said 'play as you've never played before', not 'play as IF you've never
played before'!"
- Andy Capp

Dan Pop

unread,
Feb 12, 2003, 9:37:35 AM2/12/03
to

Depending on your purposes, it can be more useful than a variable,
because it can be used in places where variables cannot, like constant
expressions.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Dan...@ifh.de

Karl Heinz Buchegger

unread,
Feb 12, 2003, 10:04:48 AM2/12/03
to

ava...@pride.hofstra.spam.edu wrote:
>
>
> Sure, I understand the idea behind a global variable, so I guess the
> question is if I'm only using the define as a global variable, is there
> any benefit over simply assigning a global variable in the main() of a
> program?
>

I think its time to look of the mechanism thats behind that #define

Guess what: the real compiler never sees them!
Part of the compilation process is the so called 'preprocessor'.
The preprocessor is a sort of text editor which can be controlled
by those funny looking # lines.
All the preprocessor does is text replacement. Not more, not less.

Imagine your program looks like this

#define LINE_LENGTH 512

int main()
{
int i;

for( i = 0; i < LINE_LENGTH; i++ ) {
}
}

The first step in compilation is the preprocessing stage. The preprocessor
reads the file and sees the
#define LINE_LENGTH 512

In its internarl tables, it creates an entry for LINE_LENGTH, together with the
replacement text: 512
When the preprocessor finally reaches the line
for( i = 0; i < LINE_LENGTH; i++ ) {

it finds the text LINE_LENGTH in it. Since it also finds a replacement text for that,
it does the substitution:

for( i = 0; i < 512; i++ ) {

When the preprocessor has finished its work, this is what comes out of it:

int main()
{
int i;

for( i = 0; i < 512; i++ ) {
}
}

And this is also, what is sent to the real compiler to be converted into
machine code.
So in a nutshell: The preprocessor has no idea about C syntax or semantics.
It doesn't know about C-variables or something else. All it does is
text replacements. The very same text replacements you do in your editor
when you tell your editor to replace every occourence of 'LINE_LENGTH' with
'512'. Only in your text editor you use some menue to initiate the action,
while here you use
#define ........
to do the very same.

--
Karl Heinz Buchegger
kbuc...@gascad.at

Joona I Palaste

unread,
Feb 12, 2003, 10:26:15 AM2/12/03
to
Karl Heinz Buchegger <kbuc...@gascad.at> scribbled the following:

> ava...@pride.hofstra.spam.edu wrote:
>> Sure, I understand the idea behind a global variable, so I guess the
>> question is if I'm only using the define as a global variable, is there
>> any benefit over simply assigning a global variable in the main() of a
>> program?

> I think its time to look of the mechanism thats behind that #define

> Guess what: the real compiler never sees them!
> Part of the compilation process is the so called 'preprocessor'.
> The preprocessor is a sort of text editor which can be controlled
> by those funny looking # lines.
> All the preprocessor does is text replacement. Not more, not less.

(snip)

> So in a nutshell: The preprocessor has no idea about C syntax or semantics.
> It doesn't know about C-variables or something else. All it does is
> text replacements. The very same text replacements you do in your editor
> when you tell your editor to replace every occourence of 'LINE_LENGTH' with
> '512'. Only in your text editor you use some menue to initiate the action,
> while here you use
> #define ........
> to do the very same.

Not exactly.
Consider this program:

#define LINE_LENGTH 512
#include <stdio.h>
int main(void) {
printf("LINE_LENGTH is: %d\n", LINE_LENGTH);
return 0;
}

According to your explanation, this would print:
512 is: 512
However, it prints:
LINE_LENGTH is: 512

This is because the preprocessor *does* have a clue about C syntax. It
goes as far as the lexing stage, i.e. converting characters into tokens
(lexemes). Then it stops. It doesn't care a toss about what sort of
syntactic trees those tokens make up.

--
/-- Joona Palaste (pal...@cc.helsinki.fi) ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/

"A computer program does what you tell it to do, not what you want it to do."
- Anon

Karl Heinz Buchegger

unread,
Feb 12, 2003, 10:30:30 AM2/12/03
to

Joona I Palaste wrote:
>
> This is because the preprocessor *does* have a clue about C syntax. It
> goes as far as the lexing stage, i.e. converting characters into tokens
> (lexemes). Then it stops. It doesn't care a toss about what sort of
> syntactic trees those tokens make up.

Right, of course.
Thanks for clearification.

ava...@pride.hofstra.spam.edu

unread,
Feb 12, 2003, 11:52:21 AM2/12/03
to
Karl Heinz Buchegger wrote:
>
> Joona I Palaste wrote:
>
>>This is because the preprocessor *does* have a clue about C syntax. It
>>goes as far as the lexing stage, i.e. converting characters into tokens
>>(lexemes). Then it stops. It doesn't care a toss about what sort of
>>syntactic trees those tokens make up.
>
>
> Right, of course.
> Thanks for clearification.
>
>

Ah! Big lightbulb from that explanation. Thanks so much! That's the
answer to WHY you can do all those things with #define and WHY it
doesn't have certain things like types. I really appreciate the help
everyone.

Thanks a million,
A.V.

Dan Pop

unread,
Feb 12, 2003, 11:46:56 AM2/12/03
to
In <b2dp2n$oe7$1...@oravannahka.helsinki.fi> Joona I Palaste <pal...@cc.helsinki.fi> writes:

>This is because the preprocessor *does* have a clue about C syntax.

Nope, it doesn't.

>It
>goes as far as the lexing stage, i.e. converting characters into tokens
>(lexemes).

Into preprocessing tokens, not into C tokens. The two are not the same:
123abc is a valid preprocessing number token, but not a valid C token.

E. Robert Tisdale

unread,
Feb 12, 2003, 12:28:13 PM2/12/03
to
ava...@pride.hofstra.spam.edu wrote:

> What's the benefit of using #define for variables
> as opposed to defining a variable in main?

#define isn't usually used for variables.
Using #define to define constants in C programs
is poor programming practice.

COMMANDMENTS:

1. Thou shalt not declare variables where constants are required.
Write

const int a = 7;

instead of

int a = 666; /* This is a sin! */

if a isn't supposed to change value.

2. Thou shalt not use #define to declare constants.
Write

const int a = 7;

instead of

#define a 666 /* This is a sin! */

3. Thou shalt limit variables and constants
to the narrowest scope possible.
Write

int main(int argc, char* argv[]) {
const int a = 7;
/* a used only in function main() */
return 0;
}

instead of

const int a = 7;
int main(int argc, char* argv[]) {
/* a used only in function main() */
return 0;
}

Global constants are OK but global variables are sinful.


Paul Mensonides

unread,
Feb 12, 2003, 2:28:51 PM2/12/03
to
Dan Pop wrote:
> In <b2dp2n$oe7$1...@oravannahka.helsinki.fi> Joona I Palaste
> <pal...@cc.helsinki.fi> writes:
>
>> This is because the preprocessor *does* have a clue about C syntax.
>
> Nope, it doesn't.
>
>> It
>> goes as far as the lexing stage, i.e. converting characters into
>> tokens (lexemes).
>
> Into preprocessing tokens, not into C tokens. The two are not the
> same: 123abc is a valid preprocessing number token, but not a valid C
> token.

It still has to do it on #if and #elif directives.

Paul Mensonides


those who know me have no need of my name

unread,
Feb 13, 2003, 1:39:22 AM2/13/03
to
in comp.lang.c i read:

>2. Thou shalt not use #define to declare constants.
> Write
>
> const int a = 7;
>
> instead of
>
> #define a 666 /* This is a sin! */

this commandment requires thought, not blind obedience. why? well, `a` is
not a constant according to the meaning of that term as provided by the
standard, merely a variable which you intend to be read-only. use of the
macro causes text replacement hence the literal value will be present and
constitutes a compile-time constant.

as i just noted in another response, often enum can come to your rescue, in
that enumeration constants are allowed to use identifiers, e.g.,

enum { a = 7 };

but the standard specifies that enumeration constants have type `int', so
the range is limited if the code is to be portable across the widest number
of platforms.

--
bringing you boring signatures for 17 years

Richard Bos

unread,
Feb 13, 2003, 3:36:28 AM2/13/03
to
"E. Robert Tisdale" <E.Robert...@jpl.nasa.gov> wrote:

> 2. Thou shalt not use #define to declare constants.
> Write
>
> const int a = 7;
>
> instead of
>
> #define a 666 /* This is a sin! */

Stop applying C++ rules to C. The two languages are _not_ the same.

Richard

Dan Pop

unread,
Feb 13, 2003, 5:28:38 AM2/13/03
to

^^
It has to do WHAT?

E. Robert Tisdale

unread,
Feb 13, 2003, 11:34:13 AM2/13/03
to
something that I don't know wrote:

>>2. Thou shalt not use #define to declare constants.
>> Write
>>
>> const int a = 7;
>>
>> instead of
>>
>> #define a 666 /* This is a sin! */
>

> This commandment requires thought, not blind obedience. why? well, `a` is


> not a constant according to the meaning of that term as provided by the
> standard, merely a variable which you intend to be read-only. use of the
> macro causes text replacement hence the literal value will be present and
> constitutes a compile-time constant.

$ cat tst.c
#include<stdio.h>

int main(int argc, char* argv[]) {

#ifdef EFINE_MACRO
#define a 7
#else /*EFINE_MACRO */


const int a = 7;

#endif/*EFINE_MACRO */
fprintf(stdout, "%d = a\n", a);
return 0;
}

$ gcc -O2 -Wall -ansi -pedantic -S tst.c
$ mv tst.s tst.sold
$ gcc -DEFINE_MACRO -O2 -Wall -ansi -pedantic -S tst.c
$ diff tst.s tst.sold
$ gcc --version
gcc (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE.

The ANSI/ISO C standard does not specify
the representation of data objects.

Paul Mensonides

unread,
Feb 13, 2003, 5:03:14 PM2/13/03
to

It has to produce real tokens, not just pp-tokens, in order to evaluate
expressions.

Paul Mensonides


those who know me have no need of my name

unread,
Feb 13, 2003, 11:58:16 PM2/13/03
to
in comp.lang.c i read:

>something that I don't know wrote:

>>>2. Thou shalt not use #define to declare constants.

>> This commandment requires thought, not blind obedience.

> $ gcc -O2 -Wall -ansi -pedantic -S tst.c


> $ mv tst.s tst.sold
> $ gcc -DEFINE_MACRO -O2 -Wall -ansi -pedantic -S tst.c
> $ diff tst.s tst.sold
> $ gcc --version
> gcc (GCC) 3.2 20020903 (Red Hat Linux 8.0 3.2-7)

ah yes, a particular implementation is always proper proof. not.

try your little test again with strings.

>The ANSI/ISO C standard does not specify
>the representation of data objects.

this is untrue. it doesn't specify the representation of the type you've
used.

Dan Pop

unread,
Feb 14, 2003, 6:42:59 AM2/14/03
to

Chapter and verse, please.

pete

unread,
Feb 14, 2003, 11:14:53 AM2/14/03
to
those who know me have no need of my name wrote:
>
> in comp.lang.c i read:
> >something that I don't know wrote:
>
> >>>2. Thou shalt not use #define to declare constants.

I use #define to declare constants when I have conditional
compilation which depends on the value of the constant.

--
pete

CBFalconer

unread,
Feb 14, 2003, 2:29:23 PM2/14/03
to

Foolishness. Use a define to provide an isolated place to control
various slaved values or to add clarity.

--
Chuck F (cbfal...@yahoo.com) (cbfal...@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!


Thomas Stegen

unread,
Feb 14, 2003, 3:09:25 PM2/14/03
to
Joona I Palaste wrote:

> This is because the preprocessor *does* have a clue about C syntax. It
> goes as far as the lexing stage, i.e. converting characters into tokens
> (lexemes).

Just a nit. Lexemes and tokens are not the same. A lexeme can
roughly be viewed as specific token. For example if the token
is IDENTIFIER (as in a terminal) then possible lexemes include
(depending on the grammar of course) i_am_an_identifier, foo, bar
etc.

But I digress :)

--
Thomas.

Paul Mensonides

unread,
Feb 14, 2003, 6:04:52 PM2/14/03
to
Dan Pop wrote:

>> It has to produce real tokens, not just pp-tokens, in order to
>> evaluate expressions.
>
> Chapter and verse, please.

6.10.1/2

The controlling expression is a "constant-expression" which reduces to a
"primary-expression" after going through a bunch of other grammar productions
that provide the associativity and evaluation order of all operators that are
valid in a "constant-expression."

Likewise, 6.6/4 says that the value must evaluate to a representable value.
Therefore,

#if 0UL - 1

...is an error, but...

#if 0 - 1

...is not.

Paul Mensonides


CBFalconer

unread,
Feb 14, 2003, 9:54:40 PM2/14/03
to

Not so. 0UL - 1 evaluates to UINT_MAX, which is representable.

Jirka Klaue

unread,
Feb 14, 2003, 9:58:25 PM2/14/03
to
CBFalconer wrote:
...

> 0UL - 1 evaluates to UINT_MAX, which is representable.

ITYM ULONG_MAX. Would smash my world view otherwise.

Jirka

Paul Mensonides

unread,
Feb 14, 2003, 10:45:04 PM2/14/03
to
CBFalconer wrote:

> Paul Mensonides wrote:
>
>> Likewise, 6.6/4 says that the value must evaluate to a representable
>> value. Therefore,
>>
>> #if 0UL - 1
>>
>> ...is an error, but...
>>
>> #if 0 - 1
>>
>> ...is not.
>
> Not so. 0UL - 1 evaluates to UINT_MAX, which is representable.

How would a "constant-expression" not be representable then? Division by zero?
The only other way it could be possible is with a single literal that is too
large, which is only a "constant-expression" in the loosest sense of the word.
Why not just say that integral constants must be representable? The value of
zero minus one is technically negative one, which is not representable as an
unsigned integer. I can certainly see your point-of-view, but how else is that
part of the standard to be interpreted?

Paul Mensonides


pete

unread,
Feb 15, 2003, 1:27:26 AM2/15/03
to
CBFalconer wrote:
>
> pete wrote:
> > those who know me have no need of my name wrote:
> > > in comp.lang.c i read:
> > > >something that I don't know wrote:
> > >
> > > >>>2. Thou shalt not use #define to declare constants.
> >
> > I use #define to declare constants when I have conditional
> > compilation which depends on the value of the constant.
>
> Foolishness. Use a define to provide an isolated place to control
> various slaved values or to add clarity.

How would I do that in the following situation? :

I have a program which compares the performance of various
sorting functions. The various sorting functions are #defined
1 through 15. I also have two #defines for F_0 and F_1.
The values for F_0 and F_1 are selected from the #defines for
the various functions. When (F_0 != F_1), then the program
sets counters in the swapping macro and in the compare function
and then the program displays the number of comparisons
and swaps in the two different functions.

/********************************************************************/
0: h_sort 50199 Cmp 45612 Swp, qisort 48726 Cmp 13136 Swp
1: h_sort 50246 Cmp 45683 Swp, qisort 51710 Cmp 13067 Swp
2: h_sort 50147 Cmp 45614 Swp, qisort 50888 Cmp 13084 Swp
3: h_sort 50083 Cmp 45594 Swp, qisort 48718 Cmp 13102 Swp
4: h_sort 50165 Cmp 45656 Swp, qisort 47502 Cmp 13268 Swp
5: h_sort 50142 Cmp 45619 Swp, qisort 49203 Cmp 13157 Swp
6: h_sort 50185 Cmp 45675 Swp, qisort 50209 Cmp 13063 Swp
7: h_sort 50231 Cmp 45720 Swp, qisort 49991 Cmp 13112 Swp
8: h_sort 50205 Cmp 45698 Swp, qisort 48187 Cmp 13154 Swp
9: h_sort 50189 Cmp 45656 Swp, qisort 50109 Cmp 12988 Swp

10 Trials, 4000 keys, 1000000000 possible key values

total h_sort comparrisons: 501792
total qisort comparrisons: 495243

total h_sort swaps: 456527
total qisort swaps: 131131
/*******************************************************************/

When (F_0 == F_1)
then the program removes the counters and just reports time.

/*******************************************************************/
1 Trial, 4000000 keys, 1000000000 possible key values
qisort: 3.203000 seconds
/*******************************************************************/

I have the code like this:

#define KEY_RANGE 1000000000LU
#define SEQUENCE RANDOM /*FORWARD/*REVERSE*/
#define SEED_RAND /*(unsigned)time(0) /*/ 1U
#define TIMED_TYPE unsigned /*/ long double */
#define ARRAY_ELEM 4000000LU
#define TRIALS 1LU
#define F_0 QISORT
#define F_1 QISORT

/* BEGIN #define values for F_0 and F_1 */
#define DUMMMY 0 /* for timing loops, doesn't sort */
#define QSORT_ 1 /* standard library qsort */
#define B_SORT 2 /* bubblesort */
#define C_SORT 3 /* cocktail shaker bubblesort */
#define I_SORT 4 /* insertion sort */
#define S_SORT 5 /* shellsort */
#define H_SORT 6 /* heapsort */
#define Q_SORT 7 /* very simple recursive quicksort */
#define Q0SORT 8 /* quicksort with recursion control */
#define Q1SORT 9 /* Sedgewick style inner loops */
#define Q2SORT 10 /* nonrecursive quicksort */
#define Q3SORT 11 /* median of 3 quicksort */
#define QISORT 12 /* biased introspective quicksort */
#define Q4SORT 13 /* sort 4 special */
#define HSORT5 14 /* John Bently */
#define HISORT 15 /* */
/* END #define values for F_0 and F_1 */

/* These have to match the order of values for F_0 and F_1 */
#define FUNCTION_POINTERS_AND_STRING_POINTERS { \
{dummmy, "dummmy"}, \
{ qsort, " qsort"}, \
{b_sort, "b_sort"}, \
{c_sort, "c_sort"}, \
{i_sort, "i_sort"}, \
{s_sort, "s_sort"}, \
{h_sort, "h_sort"}, \
{q_sort, "q_sort"}, \
{q0sort, "q0sort"}, \
{q1sort, "q1sort"}, \
{q2sort, "q2sort"}, \
{q3sort, "q3sort"}, \
{qisort, "qisort"}, \
{q4sort, "q4sort"}, \
{hsort5, "hsort5"}, \
{hisort, "hisort"}, \
}

#define NOT_TIMED (F_0 != F_1)

#if NOT_TIMED
typedef unsigned ETYPE;
#define INC_SwapCounter ((void)++SwapCounter)
#define INC_CompCounter ((void)++CompCounter)
#define ARRAY_BYTES (2 * sizeof *array)
#else
typedef TIMED_TYPE ETYPE;
#define INC_SwapCounter ((void)0)
#define INC_CompCounter ((void)0)
#define ARRAY_BYTES (sizeof *array)
#endif

and there's also some other #if NOT_TIMED parts in main.

--
pete

CBFalconer

unread,
Feb 15, 2003, 3:19:32 AM2/15/03
to
pete wrote:
>
> CBFalconer wrote:
> >
> > pete wrote:
> > > those who know me have no need of my name wrote:
> > > > in comp.lang.c i read:
> > > > >something that I don't know wrote:
> > > >
> > > > >>>2. Thou shalt not use #define to declare constants.
> > >
> > > I use #define to declare constants when I have conditional
> > > compilation which depends on the value of the constant.
> >
> > Foolishness. Use a define to provide an isolated place to control
> > various slaved values or to add clarity.
>
> How would I do that in the following situation? :
>
> I have a program which compares the performance of various
> sorting functions. The various sorting functions are #defined

I didn't mean foolish to control conditionals, I meant foolish to
restrict usage to that. I guess it didn't come across that way.

Bruce G. Stewart

unread,
Feb 15, 2003, 10:25:00 PM2/15/03
to

Hello new world view. I think he means it.

Jirka Klaue

unread,
Feb 16, 2003, 7:14:35 PM2/16/03
to

May be. He could still be mistaken. :-)
0UL - 1 should be ULONG_MAX which could overflow an unsigned int.

Jirka

Bruce G. Stewart

unread,
Feb 16, 2003, 10:27:54 PM2/16/03
to
On Mon, 17 Feb 2003 01:14:35 +0100, Jirka Klaue
<jkl...@ee.tu-berlin.de> wrote:

>Bruce G. Stewart wrote:
>> On Sat, 15 Feb 2003 03:58:25 +0100, Jirka Klaue
>> <jkl...@ee.tu-berlin.de> wrote:
>>
>>>CBFalconer wrote:
>>>...
>>>
>>>>0UL - 1 evaluates to UINT_MAX, which is representable.
>>>
>>>ITYM ULONG_MAX. Would smash my world view otherwise.
>>
>> Hello new world view. I think he means it.
>
>May be. He could still be mistaken. :-)
>0UL - 1 should be ULONG_MAX which could overflow an unsigned int.

Oops. I guess it's half his world view and half yours. Since this is
in the context of a #if directive,

"Preprocessing directives of the forms
# if constant-expression new-line groupopt
# elif constant-expression new-line groupopt
check whether the controlling constant expression evaluates to
nonzero.

"The resulting tokens compose the controlling constant expression
which is evaluated according to the rules of 6.6, except that all
signed integer types and all unsigned integer types act as if they
have the same representation as, respectively, the types intmax_t and
uintmax_t defined in the header <stdint.h>."

etc...

uintmax_t being the widest integer type, ULONG_MAX is more likely than
UINT_MAX. bUT, since all integer types are the same to preprocessor
directives, and since uintmax_t is the widest type, there's nothing to
overflow.

Bruce G. Stewart

unread,
Feb 16, 2003, 10:46:26 PM2/16/03
to

That's an interesting question. On the face of it, if the normal rules
of c expressions are followed, it seems a tautological - if an
expression can be evalutated at all, the result can be represented by
it's type. Do evaluation rules for constant expressions differ from
the usual arithmetic conversions? If so, what rules determine the type
of such an expression?

Is it undefined behavior to provide a floating constant that cannot be
represented exactly as a double?

Or was the rule intended to disallow integer constants outside the
range of [INTMAX_MIN..UINTMAX_MAX], etc?

Dan Pop

unread,
Feb 17, 2003, 6:55:54 AM2/17/03
to
In <nCe3a.102373$SD6.5497@sccrnsc03> "Paul Mensonides" <leav...@attbi.com> writes:

>Dan Pop wrote:
>
>>> It has to produce real tokens, not just pp-tokens, in order to
>>> evaluate expressions.
>>
>> Chapter and verse, please.
>
>6.10.1/2
>
>The controlling expression is a "constant-expression" which reduces to a
>"primary-expression" after going through a bunch of other grammar productions
>that provide the associativity and evaluation order of all operators that are
>valid in a "constant-expression."

Let's have a closer look:

3 Prior to evaluation, macro invocations in the list of
preprocessing tokens that will become the controlling constant
expression are replaced (except for those macro names modified
by the defined unary operator), just as in normal text. If the
token defined is generated as a result of this replacement
process or use of the defined unary operator does not match
one of the two specified forms prior to macro replacement,
the behavior is undefined. After all replacements due to macro
expansion and the defined unary operator have been performed,
all remaining identifiers are replaced with the pp-number 0,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
and then each preprocessing token is converted into a token.
========^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

That's definitely not the same way of producing real tokens as in the
translation phase 7. E.g. the sizeof "identifier" will be replaced by the
pp-number 0.

>Likewise, 6.6/4 says that the value must evaluate to a representable value.
>Therefore,
>
>#if 0UL - 1
>
>...is an error, but...

Nope, it's a valid expression evaluating to UINTMAX_MAX, because it
is equivalent to the C expression (uintmax_t)0 - (intmax_t)1.

From the same paragraph:

The resulting tokens compose the controlling constant expression
which is evaluated according to the rules of 6.6, except that
all signed integer types and all unsigned integer types act
as if they have the same representation as, respectively,
the types intmax_t and uintmax_t defined in the header
<stdint.h>.

Dan

Paul Mensonides

unread,
Feb 17, 2003, 2:04:27 PM2/17/03
to
Dan Pop wrote:

> Let's have a closer look:
>
> 3 Prior to evaluation, macro invocations in the list of
> preprocessing tokens that will become the controlling constant
> expression are replaced (except for those macro names modified
> by the defined unary operator), just as in normal text. If the
> token defined is generated as a result of this replacement
> process or use of the defined unary operator does not match
> one of the two specified forms prior to macro replacement,
> the behavior is undefined. After all replacements due to macro
> expansion and the defined unary operator have been performed,
> all remaining identifiers are replaced with the pp-number 0,
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> and then each preprocessing token is converted into a token.
> ========^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> That's definitely not the same way of producing real tokens as in the
> translation phase 7. E.g. the sizeof "identifier" will be replaced
> by the pp-number 0.

Hi Dan,

I didn't mean that it does an absolutely complete tokenization. I does however
have to properly tokenize all numbers and symbolic operators. My only point was
that the preprocessor does have to produce normal tokens in some contexts.

>> Likewise, 6.6/4 says that the value must evaluate to a representable
>> value. Therefore,
>>
>> #if 0UL - 1
>>
>> ...is an error, but...
>
> Nope, it's a valid expression evaluating to UINTMAX_MAX, because it
> is equivalent to the C expression (uintmax_t)0 - (intmax_t)1.

Is that defined to be true in the standard? I.e. is it mandated that unsigned
integral underflow must wrap? I'm interesting in your interpretation of what
constitutes an "unrepresentable constant expression."

Paul Mensonides


Dan Pop

unread,
Feb 18, 2003, 5:19:38 AM2/18/03
to
In <%ma4a.153196$be.132066@rwcrnsc53> "Paul Mensonides" <leav...@attbi.com> writes:

>Dan Pop wrote:
>
>> Let's have a closer look:
>>
>> 3 Prior to evaluation, macro invocations in the list of
>> preprocessing tokens that will become the controlling constant
>> expression are replaced (except for those macro names modified
>> by the defined unary operator), just as in normal text. If the
>> token defined is generated as a result of this replacement
>> process or use of the defined unary operator does not match
>> one of the two specified forms prior to macro replacement,
>> the behavior is undefined. After all replacements due to macro
>> expansion and the defined unary operator have been performed,
>> all remaining identifiers are replaced with the pp-number 0,
>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> and then each preprocessing token is converted into a token.
>> ========^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>
>> That's definitely not the same way of producing real tokens as in the
>> translation phase 7. E.g. the sizeof "identifier" will be replaced
>> by the pp-number 0.
>
>Hi Dan,
>
>I didn't mean that it does an absolutely complete tokenization. I does however
>have to properly tokenize all numbers and symbolic operators. My only point was
>that the preprocessor does have to produce normal tokens in some contexts.

And my point was that those tokens are NOT *normal* C tokens, therefore
it is incorrect to claim that the preprocessor is aware of the C syntax,
even if only at tokenisation level.

>>> Likewise, 6.6/4 says that the value must evaluate to a representable
>>> value. Therefore,
>>>
>>> #if 0UL - 1
>>>
>>> ...is an error, but...
>>
>> Nope, it's a valid expression evaluating to UINTMAX_MAX, because it
>> is equivalent to the C expression (uintmax_t)0 - (intmax_t)1.
>
>Is that defined to be true in the standard? I.e. is it mandated that unsigned
>integral underflow must wrap?

Yup.

>I'm interesting in your interpretation of what
>constitutes an "unrepresentable constant expression."

Something like INTMAX_MAX + 1, in the context of this discussion.

Reply all
Reply to author
Forward
0 new messages