defining the size_t type

L

lubomir dobsik

hi, i have seen an interesting thing:

#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)
typedef unsigned int size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long)
typedef unsigned long size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long long)
typedef unsigned long long size_t;
#endif

is this way of defining the size_t portable?

cheers, lubos
 
S

santosh

lubomir said:
hi, i have seen an interesting thing:

#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)
typedef unsigned int size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long)
typedef unsigned long size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long long)
typedef unsigned long long size_t;
#endif

is this way of defining the size_t portable?

As far as I know sizeof cannot be used with the conditional compilation
directives. This may be a compiler specific extension.
 
E

Eric Sosman

lubomir dobsik wrote On 10/25/07 10:42,:
hi, i have seen an interesting thing:

#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)
typedef unsigned int size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long)
typedef unsigned long size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long long)
typedef unsigned long long size_t;
#endif

is this way of defining the size_t portable?

No.

One problem is that conditional compilation occurs
before types exist, so casts don't work and `sizeof'
cannot be evaluated. (At this stage of compilation,
`sizeof' and `char' and `unsigned' and `int' and `long'
are not even recognized as keywords.)

Another problem is that size_t might be something
other than the three types you test for.

Still another problem is that sizes do not determine
types. If `sizeof(size_t) == sizeof(unsigned int)' you
cannot conclude that `size_t' and `unsigned int' are the
same, just as you cannot conclude that `int' and `float'
are the same even if their sizes agree.

Even yet still another additional problem is that
you're trying to infer the type of `size_t' by examining
the size of `ptrdiff_t', a different type altogether.

Moreover still another additional accompanying extra
problem is that the attempt to define `size_t' is illegal
in any module that includes any of the several Standard
headers that define it for themselves.

But the biggest problem of all is that it's stupid.
Use a header; that's what they're for.
 
R

Richard Tobin

lubomir dobsik said:
#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)

The difference between two pointers is of type ptrdiff_t, not size_t.
You could use sizeof(sizeof(0)), if it weren't for the other problems
in your code.

-- Richard
 
K

Keith Thompson

lubomir dobsik said:
hi, i have seen an interesting thing:

#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)
typedef unsigned int size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long)
typedef unsigned long size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long long)
typedef unsigned long long size_t;
#endif

is this way of defining the size_t portable?

No, for all the reasons that have already been mentioned. Where did
you see it?

If you're not writing an implementation, then you don't need to define
size_t; the implementation will do it for you.

If you are writing an implementation, you don't need a portable
definition. You can use whatever compiler-specific magic you like, as
long as it produces the correct results. If you happen to know that
your preprocessor handles sizeof (it's not required to, and I'm not
certain it's allowed to), then you can take advantage of that, though
as Richard Tobin mentions, ``(sizeof sizeof 0)'' would make more
sense.

The only context where the above would make sense is if you're writing
a <stddef.h> to be used with several different implementations (say,
the same compiler on several different platforms). But even then,
there are likely to be cleaner ways to do it.
 
C

Chris Torek

If you are writing an implementation, you don't need a portable
definition [for size_t]. You can use whatever compiler-specific
magic you like, as long as it produces the correct results. If
you happen to know that your preprocessor handles sizeof (it's
not required to, and I'm not certain it's allowed to), then ...

It is "allowed to" in certain circumstances.

At this point in translation, pp-tokens that are not otherwise
"special" -- by which I mean pp-tokens that will map to C keywords
or ordinary identifiers -- are to be treated as if they were the
integer constant zero. Hence:

/* do not #define XYZ */

#define FOUR 4
#if FOUR == XYZ
# error "this #error must not fire"
#endif

#if XYZ == 0
# error "this #error must fire"
#endif

Because of this rule, the line:

#if sizeof(int) == 2

must be treated as if it read:

#if 0(0) == 2

(assuming, of course, you have not "#define"d sizeof and/or int).
Because this is syntactically invalid, the compiler is required
to emit "at least one diagnostic".

Once the "at least one diagnostic" has been produced, however, the
compiler can then "look back" at the original text, discover the
sizeof and int, and compute the size of an int. So you might get
the "diagnostic":

foo.c:12: congratulations on your commitment to the Frobozz compiler!

which thanks you for making sure your code will not port to other
C compilers, so that you will have to continue paying the $10,000-
per-hour fee to use the Frobozz-branded compiler. :)
The only context where the above would make sense is if you're writing
a <stddef.h> to be used with several different implementations (say,
the same compiler on several different platforms). But even then,
there are likely to be cleaner ways to do it.

Indeed -- for instance, the compiler can pre-"#define" various
names that live in the implementor's name space (i.e., the one you,
the implementor, are allowed to use because your customer, the C
programmer, is *not* allowed to use it). Thus:

#if __int_size == 2
... code that depends on sizeof(int) == 2 ...
#elif __int__size == 4
... code that depends on sizeof(int) == 4 ...
#else
#error "oops: internal implementation error with __int_size"
#endif

Note that we can construct cases where the "sizeof" keyword must
be replaced, during "#if" arithmetic, with the integer constant
zero, and the result is still syntactically valid:

#if sizeof + 0 != 0
# error "this compiler is broken"
#endif

This makes implementing Frobozz C correctly quite tricky.
 
E

Eric Sosman

Chris said:
[... concerning sizeof, etc., in #if directives ...]
At this point in translation, pp-tokens that are not otherwise
"special" -- by which I mean pp-tokens that will map to C keywords
or ordinary identifiers -- are to be treated as if they were the
integer constant zero. [...]

Are you sure pp-tokens that will eventually become keywords
are treated differently than others? It's my understanding that,
for example,

#if return == while

is equivalent to

#if 0 == 0

5.1.1.2 says that preprocessing directives are handled in phase 4
before pp-tokens become tokens in phase 7. 6.4 describes the
keywords as a subset of the tokens, and 6.4p3 includes "keywords"
in the list of possible tokens but not in the list of pp-tokens.
 
K

Keith Thompson

Chris Torek said:
If you are writing an implementation, you don't need a portable
definition [for size_t]. You can use whatever compiler-specific
magic you like, as long as it produces the correct results. If
you happen to know that your preprocessor handles sizeof (it's
not required to, and I'm not certain it's allowed to), then ...

It is "allowed to" in certain circumstances.

At this point in translation, pp-tokens that are not otherwise
"special" -- by which I mean pp-tokens that will map to C keywords
or ordinary identifiers -- are to be treated as if they were the
integer constant zero. Hence:

/* do not #define XYZ */

#define FOUR 4
#if FOUR == XYZ
# error "this #error must not fire"
#endif

#if XYZ == 0
# error "this #error must fire"
#endif

Because of this rule, the line:

#if sizeof(int) == 2

must be treated as if it read:

#if 0(0) == 2

(assuming, of course, you have not "#define"d sizeof and/or int).
Because this is syntactically invalid, the compiler is required
to emit "at least one diagnostic".

Once the "at least one diagnostic" has been produced, however, the
compiler can then "look back" at the original text, discover the
sizeof and int, and compute the size of an int. So you might get
the "diagnostic":

foo.c:12: congratulations on your commitment to the Frobozz compiler!

which thanks you for making sure your code will not port to other
C compilers, so that you will have to continue paying the $10,000-
per-hour fee to use the Frobozz-branded compiler. :)
[...]

Right. Note that it must produce this diagnostic on conforming mode.
It's likely that the Frobozz C compiler works in a non-conforming mode
by default, in which it needn't produce the diagnostic.

(I'd love to see a compiler that, in its default mode, is fully
conforming, implements no extensions, and rejects any source file that
violates a syntax rule or constraint.)
 
K

Keith Thompson

Eric Sosman said:
Chris said:
[... concerning sizeof, etc., in #if directives ...]
At this point in translation, pp-tokens that are not otherwise
"special" -- by which I mean pp-tokens that will map to C keywords
or ordinary identifiers -- are to be treated as if they were the
integer constant zero. [...]

Are you sure pp-tokens that will eventually become keywords
are treated differently than others?
[...]

He didn't say they were. He referred to "pp-tokens that will map to C
keywords or ordinary identifiers".
 
L

lubomir dobsik

hi, i have seen an interesting thing:

#if sizeof((char*)0 - (char*)0) == sizeof(unsigned int)
typedef unsigned int size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long)
typedef unsigned long size_t;
#elif sizeof((char*)0 - (char*)0) == sizeof(unsigned long long)
typedef unsigned long long size_t;
#endif

is this way of defining the size_t portable?

cheers, lubos


thanks all for the reactions. the snippet comes from the stddef.h of a
particular compiler. i admit that under these circumstances my
original question doesnt make much sense. anyway, i posted this
because i was curious to see your comments on this rather than getting
a yes/no answer. thanks again, lubos
 
K

Keith Thompson

lubomir dobsik said:
thanks all for the reactions. the snippet comes from the stddef.h of a
particular compiler. i admit that under these circumstances my
original question doesnt make much sense. anyway, i posted this
because i was curious to see your comments on this rather than getting
a yes/no answer. thanks again, lubos

Interesting. Which compiler is it? I wonder whether the compiler
actually recognizes "sizeof" in preprocessor directives, or perhaps
the author of stddef.h just *thought* it did.
 
L

lubomir dobsik

Interesting. Which compiler is it? I wonder whether the compiler
actually recognizes "sizeof" in preprocessor directives, or perhaps
the author of stddef.h just *thought* it did.

--
Keith Thompson (The_Other_Keith) (e-mail address removed) <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."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

it was IAR, and no, it doesn't recognize the sizof during
preprocessing - the #if directive with the expression containing
sizeof is nested inside of another #if directive whose expression
apparently always evaluates to false.
 
S

somenath

Keith Thompson said:
If you are writing an implementation, you don't need a portable
definition [for size_t]. You can use whatever compiler-specific
magic you like, as long as it produces the correct results. If
you happen to know that your preprocessor handles sizeof (it's
not required to, and I'm not certain it's allowed to), then ...

It is "allowed to" in certain circumstances.

At this point in translation, pp-tokens that are not otherwise
"special" -- by which I mean pp-tokens that will map to C keywords
or ordinary identifiers -- are to be treated as if they were the
integer constant zero. Hence:

/* do not #define XYZ */

#define FOUR 4
#if FOUR == XYZ
# error "this #error must not fire"
#endif

#if XYZ == 0
# error "this #error must fire"
#endif

Because of this rule, the line:

#if sizeof(int) == 2

must be treated as if it read:

#if 0(0) == 2

Sorry if I have misunderstood what you are trying to convey.
But
#if sizeof(int) == 2
#endif
Will not be compiled.
I think because as it is converted to #if 0(0) == 2

The compiler is throwing eror
foo.c:1:11: missing binary operator before '('
 
C

Chris Torek

... the line:
#if sizeof(int) == 2
must be treated as if it read:
#if 0(0) == 2
... [so that] the compiler is required to emit "at least one diagnostic".

Sorry if I have misunderstood what you are trying to convey.

I think you have:
But
#if sizeof(int) == 2
#endif
Will not be compiled.
I think because as it is converted to #if 0(0) == 2

The compiler is throwing eror
foo.c:1:11: missing binary operator before '('

This is your "at least one diagnostic".

If you have Frobozz C, *that* *particular* compiler -- which prints
a different diagnostic -- then goes on to "re-inspect" the original
line, and do something different.

No C compiler is *required* to work the way Frobozz C does, so if
you would ever like to use any *other* compiler, you should avoid
depending on the special features offered by Frobozz C.

This is true of other compilers as well. If you make use of various
gcc-specific features, you will be unable to use lcc-win32 to
compile your code; if you make use of certain lcc-win32-specific
features, you will be unable to use gcc to compile your code; and
so on. Thus, *any* time you make use of *any* compiler's special
features, you should be aware of the *cost* of your actions, as
well as the (presumed) benefit (i.e., getting the use of whatever
the "special feature" does for you).

In other words, I am not saying "do not use qfloat (lcc-win32) or
&&label (gcc) or &42 (VMS) or #pragma dwim (Frobozz)", but rather,
"be aware of BOTH the cost AND the benefit of your actions".
 

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,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top