6

Consider an unsigned char v that goes through a series of bit-wise operations with the result stored back to v. Under the hood, it is integer promoted once, undergoes a series of operations, and the result is truncated and stored back to v.

With std::byte v, however, for each and every operation, the operand is first integer promoted, undergoes the operation, and the (intermediate) result is truncated and stored back to some std::byte. That would be many back-and-forth promotion and truncation. This is all conceptual, but would it cause real overhead in practice?

Artificial Example

// `mask` and `lshf` are of type `unsigned`
unsigned char v = ...;
v = (v & mask) << lshf; // one promotion at `&` and one truncation at `=`
// `mask` and `lshf` are of type `std::byte` and `unsigned`
std::byte v = ...;
v = (v & mask) << lshf;

// It would be like
// byte(unsigned(byte(unsigned(v) & unsigned(mask))) << lshf)

Real-Case Example

Let's say we want to zero out the leading 3 bits of a byte.

unsigned char v = ...;
v = (v << 3 & 0xff) >> 3;

vs.

std::byte v = ...;
v = v << 3 >> 3;
Jan Schultke
  • 17,446
  • 6
  • 47
  • 96
Lingxi
  • 14,579
  • 2
  • 37
  • 93
  • 4
    can you show an example where the `unsigned char` is promoted once but the `std::byte` on every operation? – 463035818_is_not_an_ai May 10 '23 at 14:11
  • 2
    You'd need to look at the optimized (`-O3`) assembly, or profile. Probably does not have any appreciable overhead... but to be sure: **profile**. – Eljay May 10 '23 at 14:11
  • 1
    @463035818_is_not_a_number Added example. – Lingxi May 10 '23 at 14:21
  • 2
    @463035818_is_not_a_number If you do `(var << 3) >> 2` that has one promotion if `var` is a `unsigned char` if it is a `std::byte` it has to convert to an `unsigned int` and back to a `std::byte` for each operation. – NathanOliver May 10 '23 at 14:21
  • 1
    Anecdotally, I'd say only in unoptimized builds. See e.g. https://godbolt.org/z/E6qoxb3Kj vs. https://godbolt.org/z/scjse5Mxj – Bob__ Aug 28 '23 at 19:05

0 Answers0