A constant expression is an expression that can be evaluated
at compile time. Constants of integral or enumerated type are required
in several different situations, such as array bounds, enumerator
values, and case
labels. Null pointer
constants are a special case of integral constants.
An integral constant expression is an expression that can
be evaluated at compile time, and whose type is integral or an
enumeration. The situations that require integral constant expressions
include array bounds, enumerator values, case
labels, bit-field sizes, static member
initializers, and value template arguments. The compiler must be able
to evaluate the expression at compile time, so you can use only
literals, enumerators, const
objects that have constant initializers, integral or enumerated
template parameters, sizeof
expressions, and constant addresses. The address of a static lvalue
object is a constant address, as is the address of a function. A
string literal, being a static array of characters, is also a constant
address.
An integral static const
data
member can be initialized in the class definition if the initializer
is a constant integral or enumerated expression. The member can then
be used as a constant expression elsewhere in the class definition.
For example:
template<typename T, size_t size> class array { public: static const size_t SIZE = size; ... private: T data[SIZE]; };
See Chapter 6 for more information about static data members.
A constant expression with a value of 0
can be a null pointer
constant . A null pointer constant can be converted to a
null pointer value. The colloquial term null
pointer almost always means null pointer value.
A null pointer value has an implementation-defined bit pattern.
Many implementations use all zero bits, but some do not. Thus, the
null pointer constant is not representative of the bits that make up a
null pointer value, but serves only as a mnemonic for the programmer,
much like =
0
does for a pure virtual function (Chapter 6).
When you assign a null pointer constant to a pointer-type
variable, the compiler converts the null pointer constant to a null
pointer value of the appropriate type. Similarly, when comparing
pointers, the compiler ensures that the comparison is meaningful. In
particular, a null pointer value is never equal to any valid pointer
value, is always equal to another null pointer value, and is always
equal to a null pointer constant. A null pointer value, when converted
to bool
, is false
. A pointer that is initialized with an
empty initializer is initialized to a null pointer value.
The NULL
macro, defined in <cstdlib>
and other headers (see Chapter 13), expands to a null pointer
constant. Using NULL
instead of
0
can be a helpful reminder to the
reader or maintainer of a program, especially when typedef
s obscure the nature of a
type:
Token tok1 = 0; // Is Token a pointer or an integer? Token tok2 = NULL; // Token is probably a pointer.