Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the output format of an int8_t use 4 bytes?

Tags:

c++

For some testing purpose I want to display int8_t variables, cast them to uint8_t and display them again, in hexadecimal.

#include <iostream>
#include <sstream>

int main()
{
  std::int8_t t = -1;

  std::cout << std::hex << +t << std::endl;
  std::cout << std::hex << +static_cast<std::uint8_t>(t) << std::endl;


  return 0;
}

Here is my output for this program:

$ ./a.exe
ffffffff
ff

cout seems to format an int8_t as 4 bytes. Why is that? As it is a one-byte value, one would expect to see ff, like an uint8_t, which is the case in this example.

like image 594
Mathias B. Avatar asked Jun 12 '19 12:06

Mathias B.


3 Answers

Why is the output format of an int8_t uses 4 bytes?

It doesn't. You're outputting an int, not a int8_t.


To stream a uint8_t to std::cout with lexical conversions, you have correctly used + to trigger a promotion to int (needed because char and related types do not undergo lexical conversion with IOstreams).

But then… you've promoted it to int. So you see int-like things.

Your second line is good and ensures you don't fall foul of sign extension.

like image 121
Lightness Races in Orbit Avatar answered Nov 05 '22 19:11

Lightness Races in Orbit


The problem is that you use the unary arithmetic operator + which performs integer promotion. So your int8_t is promoted to an integer. Which with your compiler and set up is 32 bits.

The built-in unary plus operator returns the value of its operand. The only situation where it is not a no-op is when the operand has integral type or unscoped enumeration type, which is changed by integral promotion, e.g, it converts char to int or if the operand is subject to lvalue-to-rvalue, array-to-pointer, or function-to-pointer conversion.

Source: https://en.cppreference.com/w/cpp/language/operator_arithmetic

The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.

Source C++ Standard § 8.3.1.7

like image 37
Tommy Andersen Avatar answered Nov 05 '22 20:11

Tommy Andersen


A little addition to the existing answers

auto x1 = static_cast<int8_t>(-1);
// x1 has type int8_t and contains value -1

auto x2 = static_cast<uint8_t>(-1);
// x2 has type uint8_t and contains value 255 !
// uint8_t cant represent value -1

// promotion to int
auto y1 = +x1; // y1 has type int with value -1
auto y2 = +x2; // y2 has also type int with value 255

std::cout << y1 << "\n";  // output "-1"
std::cout << y2 << "\n";  // output "255"

std::cout << std::hex << y1 << "\n"; // output "ffffffff" for hex representation of -1
std::cout << std::hex << y2 << "\n"; // output "ff" for hex representation of 255

I hope this code snippet makes it l little bit easier to understand.

like image 38
Tunichtgut Avatar answered Nov 05 '22 21:11

Tunichtgut