简体   繁体   中英

Writing to a signed integer as if it is unsigned in C++

Is reinterpret_cast safe for this, and is it the best way to do this?

For example, in the code below, I have a class called ibytestream , which allows the reading of uint16_t s and int16_t s from it. ibytestream::next is a vector<unsigned char>::iterator .

inline ibytestream& operator>>(ibytestream& stream, uint16_t& data) {
    data = 0;
    data |= *stream.next++;
    data <<= 8;
    data |= *stream.next++;
    return stream;
}

inline ibytestream& operator>>(ibytestream& stream, int16_t& data) {
    return stream >> reinterpret_cast<uint16_t&>(data);
}

I don't want to duplicate the code for converting the bytes to an integer, so I used reinterpret_cast for the signed version to reuse the code from the unsigned version. It works fine on my machine, but will it work in general on other modern machines?

Yes, this is safe.

Three parts of the standard apply to make this determination:

  1. Alignment requirements of signed and unsigned types are the same
  2. Pointer casts between pointers to types with identical alignment requirements are allowed
  3. When casts between glvalues are performed, the cast is valid if the cast between the corresponding pointers is valid.

For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: unsigned char , unsigned short int , unsigned int , unsigned long int , and unsigned long long int , each of which occupies the same amount of storage and has the same alignment requirements.

An object pointer can be explicitly converted to an object pointer of a different type. Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value.

A glvalue expression of type T1 can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_cast. The result refers to the same object as the source glvalue, but with the specified type.

Yes, that should be perfectly fine. (Moving between ints and byte arrays have potential endian-ness issues, but that's another matter that applies to both signed and unsigned numbers.)

Something completely different: This bit:

data = 0;
data |= *stream.next++;

...can be simplified:

data = *stream.next++;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM