size_t and C90/C99

P

Pedro Graca

#include <stdio.h>

#ifdef C99
#define FMT_STRING "The value is %zu.\n"
#define CAST_SIZE_T
#else
#define FMT_STRING "The value is %lu.\n"
#define CAST_SIZE_T (unsigned long)
#endif

int main(void) {
size_t val=42;

printf(FMT_STRING, CAST_SIZE_T val);
return 0;
}


I don't even know for sure if the C99 macro is defined in my
implementation ... but the code compiled and run without glitches with
gcc

gcc -W -Wall -std=c89 -pedantic c9099.c -oc90
gcc -W -Wall -std=c99 -pedantic c9099.c -oc99


My questions are:

a) Is there a standard way to identify the standard being used to
compile the program (the "C99" predefined macro?)?

b) Is the way I used #ifdef usual accepted practice to code for the two
standards?
 
E

Eric Sosman

Pedro said:
#include <stdio.h>

#ifdef C99
#define FMT_STRING "The value is %zu.\n"
#define CAST_SIZE_T
#else
#define FMT_STRING "The value is %lu.\n"
#define CAST_SIZE_T (unsigned long)
#endif
[...]

My questions are:

a) Is there a standard way to identify the standard being used to
compile the program (the "C99" predefined macro?)?

#if __STDC_VERSION >= 199901
b) Is the way I used #ifdef usual accepted practice to code for the two
standards?

Nothing wrong with it that I can see.
 
P

Peter Nilsson

In terms of style, a function macro would be better IMO.
#endif
[...]

My questions are:

a) Is there a standard way to identify the standard being used to
compile the program (the "C99" predefined macro?)?

#if __STDC_VERSION__ >= 199901 [corrected]
b) Is the way I used #ifdef usual accepted practice to code for the two
standards?

Nothing wrong with it that I can see.

__STDC_VERSION__ may be set to something larger than 199901 on a C90
implementation. Using it is therefore potentially unreliable.

My alternative would be...

#include <stdio.h>
#include <limits.h>

#ifdef SIZE_MAX /* C99? */
#define FMT_PRI_SIZE_T "z"
#define CAST_PRI_SIZE_T(sz) ((size_t) (sz))
#else
#define FMT_PRI_SIZE_T "l"
#define CAST_PRI_SIZE_T(sz) ((unsigned long)(size_t) (sz))
#endif

int main(void)
{
printf("Maximum size_t value is %" FMT_PRI_SIZE_T "u.\n",
CAST_PRI_SIZE_T(-1));
return 0;
}
 
K

Keith Thompson

Peter Nilsson said:
__STDC_VERSION__ may be set to something larger than 199901 on a C90
implementation. Using it is therefore potentially unreliable.

Theoretically, yes, but I don't think that's a realistic concern.
Since the C90 standard doesn't mention __STDC_VERSION__, a C90
compiler can define it any way it likes -- but an implementation that
sets it to something larger than 199901L would be deliberately lying,
and you wouldn't be able to depend on *anything* it tells you.

If the compiler lies to me, I will get my revenge.
 
P

Peter Nilsson

Keith said:
Theoretically, yes, but I don't think that's a realistic concern.

I don't think so either, but not for the same reason that you do.

I don't think it's a concern because I think the few C90
implementations that bother to specify __STDC_VERSION__
will be those that came in after the normative additions to C90.
Since the C90 standard doesn't mention __STDC_VERSION__, a C90
compiler can define it any way it likes -- but an implementation that
sets it to something larger than 199901L would be deliberately lying,

Why would it be a _deliberate_ lie? For decades, I've been using
YYYYMMDD style in version constants of my own, even when the
gap between versions is likely to be months (even years).

I don't see why an implementor of C90 in the late 80s, who didn't
have the luxury of a crystal ball, would think that 19891101 (say)
would be unusual, let alone a _deliberate_ attempt to usurp
future C programmers!
and you wouldn't be able to depend on *anything* it tells you.

Even gcc ports can be made to set __STDC__ to 1 in _non_ conforming
mode. Do you still trust gcc? I do, for the most part.
If the compiler lies to me, I will get my revenge.

I just ask the author to modify future updates, or I hack the
compiler (or more likely a default header) myself. I don't call
it revenge, I just call it fixing a problem. But in reality, in this
case, it would be fixing a problem of my own making.
 
K

Keith Thompson

Peter Nilsson said:
I don't think so either, but not for the same reason that you do.

I don't think it's a concern because I think the few C90
implementations that bother to specify __STDC_VERSION__
will be those that came in after the normative additions to C90.

Sure, Amendment 1 (1995) introduced __STDC_VERSION__ and specified a
value of 199409L.
Why would it be a _deliberate_ lie? For decades, I've been using
YYYYMMDD style in version constants of my own, even when the
gap between versions is likely to be months (even years).

I don't see why an implementor of C90 in the late 80s, who didn't
have the luxury of a crystal ball, would think that 19891101 (say)
would be unusual, let alone a _deliberate_ attempt to usurp
future C programmers!

Before Amendment 1 was released, such an implementer would have had to
independently invent the name __STDC_VERSION__, which seems unlikely
(and I've never heard of an implementation that actually did so).
After Amendment 1, the meaning was established, and it's hard to
imagine that setting it to anything greater than 199901L would be
anything but a deliberate lie.

(This is all hypothetical, of course.)
 

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
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top