Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

the destination type, the value produced is implementation-defined. Example:

//Suppose that on this implementation, the range of signed char is -128 to +127 and

//the range of unsigned char is 0 to 255

int x = 12345;

signed char sc = x; // sc has an implementation-defined value

unsigned char uc = x; // uc is initialized to 57 (i.e., 12345 modulo 256)

Section 71.6: Underlying type (and hence size) of an enum

If the underlying type is not explicitly specified for an unscoped enumeration type, it is determined in an implementation-defined manner.

enum E { RED, GREEN, BLUE,

};

using T = std::underlying_type<E>::type; // implementation-defined

However, the standard does require the underlying type of an enumeration to be no larger than int unless both int and unsigned int are unable to represent all the values of the enumeration. Therefore, in the above code, T could be int, unsigned int, or short, but not long long, to give a few examples.

Note that an enum has the same size (as returned by sizeof) as its underlying type.

Section 71.7: Numeric value of a pointer

The result of casting a pointer to an integer using reinterpret_cast is implementation-defined, but "... is intended to be unsurprising to those who know the addressing structure of the underlying machine."

int x = 42; int* p = &x;

long addr = reinterpret_cast<long>(p);

std::cout << addr << "\n"; // prints some numeric address,

// probably in the architecture's native address format

Likewise, the pointer obtained by conversion from an integer is also implementation-defined.

The right way to store a pointer as an integer is using the uintptr_t or intptr_t types:

// `uintptr_t` was not in C++03. It's in C99, in <stdint.h>, as an optional type #include <stdint.h>

uintptr_t uip;

Version ≥ C++11

// There is an optional `std::uintptr_t` in C++11 #include <cstdint>

std::uintptr_t uip;

C++11 refers to C99 for the definition uintptr_t (C99 standard, 6.3.2.3):

an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer.

GoalKicker.com – C++ Notes for Professionals

370

While, for the majority of modern platforms, you can assume a flat address space and that arithmetic on uintptr_t is equivalent to arithmetic on char *, it's entirely possible for an implementation to perform any transformation when casting void * to uintptr_t as long the transformation can be reversed when casting back from uintptr_t to void *.

Technicalities

On XSI-conformant (X/Open System Interfaces) systems, intptr_t and uintptr_t types are required, otherwise they are optional.

Within the meaning of the C standard, functions aren't objects; it isn't guaranteed by the C standard that uintptr_t can hold a function pointer. Anyway POSIX (2.12.3) conformance requires that:

All function pointer types shall have the same representation as the type pointer to void. Conversion of a function pointer to void * shall not alter the representation. A void * value resulting from such a conversion can be converted back to the original function pointer type, using an explicit cast, without loss of information.

C99 §7.18.1:

When typedef names di ering only in the absence or presence of the initial u are defined, they shall denote corresponding signed and unsigned types as described in 6.2.5; an implementation providing one of these corresponding types shall also provide the other.

uintptr_t might make sense if you want to do things to the bits of the pointer that you can't do as sensibly with a signed integer.

Section 71.8: Number of bits in a byte

In C++, a byte is the space occupied by a char object. The number of bits in a byte is given by CHAR_BIT, which is defined in climits and required to be at least 8. While most modern systems have 8-bit bytes, and POSIX requires CHAR_BIT to be exactly 8, there are some systems where CHAR_BIT is greater than 8 i.e a single byte may be comprised of 8, 16, 32 or 64 bits.

GoalKicker.com – C++ Notes for Professionals

371