To clarify existing practice, several varieties of constant expression have been identified:

The expression following `#if`

(§3.8.1) ` `
must expand to integer constants,
character constants,
the special operator `defined`

,
and operators with no side effects. ` `
No environmental inquiries can be made,
since all arithmetic is done as translate-time
(signed or unsigned) long integers,
and casts are disallowed. ` `
The restriction to translate-time arithmetic frees an
implementation from having to perform execution-environment
arithmetic in the host environment. It does not preclude
an implementation from doing so --- the implementation may
simply define ``translate-time arithmetic'' to be that of the
target. ` `

Unsigned arithmetic is performed in these expressions
(according to the default widening rules) ` `
when unsigned operands are involved;
this rule allows for unsurprising arithmetic involving very large
constants (i.e, those whose type is `unsigned long`

) ` `
since they cannot be represented as `long`

or constants explicitly marked as unsigned. ` `

Character constants, when evaluated
in `#if`

expressions, may be interpreted in the source character
set, the execution character set, or some other implementation-defined
character set. ` `
This latitude reflects the diversity of existing practice,
especially in cross-compilers. ` `

An *integral constant expression*
must involve only numbers knowable at translate time,
and operators with no side effects. ` `
Casts and the `sizeof`

operator may be used to interrogate the execution environment. ` `

*Static initializers*
include integral constant expressions, along with floating
constants and simple addressing expressions. ` `
An implementation must accept arbitrary expressions involving
floating and integral numbers and side-effect-free operators
in arithmetic initializers, but it is at
liberty to turn such initializers into executable code which is invoked
prior to program startup (see §2.1.2.2);
this scheme might impose some requirements on linkers or runtime library
code in some implementations. ` `

The translation environment
must not produce a less accurate value
for a floating-point initializer
than the execution environment,
but it is at liberty to do better. ` `
Thus a static initializer may well be slightly different than the same
expression computed at execution time. ` `
However,
while implementations are certainly * permitted*
to produce exactly the same result
in translation and execution environments,
* requiring* this
was deemed to be an intolerable burden
on many cross-compilers.

`#if`

expressions to determine properties of
the execution environment may now get different answers. 3.3 Expressions ANSI C Rationale 3.5 Declarations