Ruslan
Ruslan

Reputation: 19140

Why is char16_t defined to have the same size as uint_least16_t instead of uint16_t?

Reading C++17 draft §6.9.1/5:

Types char16_t and char32_t denote distinct types with the same size, signedness, and alignment as uint_least16_t and uint_least32_t, respectively, in <cstdint>, called the underlying types.

Now referring to C11 draft §7.20.1.2/2, which is the reference for the C library inheritance:

The typedef name uint_leastN_t designates an unsigned integer type with a width of at least N , such that no unsigned integer type with lesser size has at least the specified width. Thus, uint_least16_t denotes an unsigned integer type with a width of at least 16 bits.

Note the "at least" part. This means that char16_t may actually have e.g. 32 bits, making an array of char16_t a bad representation of a UTF-16 raw data. In this case writing such an array to a binary file would result in valid code units alternating with U+0000 characters.

Is there a good reason for char16_t to be defined in terms of uint_least16_t instead of uint16_t? Or is it simply a defect in the standard?

Upvotes: 3

Views: 1316

Answers (2)

Pete Becker
Pete Becker

Reputation: 76448

First, as the name suggests, uint_least16_t is required to be the smallest size that can hold 16 bits. On a system with both 16- and 32-bit integers, it cannot be 32 bits.

Second, uint16_t is not required to exist. It's only there on systems that have a 16-bit integer type. Granted, those are quite common, but C and C++ are designed to impose minimal constraints on the hardware that they can target, and there are systems that don't have a 16-bit integer type.

On a system that does have a 16-bit integer type, uint16_t will be 16 bits wide (duh...), and uint_least16_t will also be 16 bits wide. On a system that doesn't have a 16-bit integer type, uint16_t won't exist, and uint_least16_t will. For code that needs to store values in a range that's representable in 16 bits, using uint_least16_t is portable. For code that needs to store exactly 16 bits (which is rare), uint16_t is the way to go.

Upvotes: 5

eerorika
eerorika

Reputation: 238421

This makes it possible to use char16_t on systems where byte size is not a factor of 16 (for example 32 bit byte, or 9 bit byte) . Such systems can have uint_least16_t but not uint16_t.

Upvotes: 4

Related Questions