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.