I need to output the hex code of char characters, but some output is crooked.

There is an array:

char a[91] = { 0x41, 0x0d, 0x61, 0x01, 0x60, 0x44, 0x69, 0x48, 0x24, 0x28, 0x60, 0x24, 0x2d, 0x2d, 0x41, 0x04, 0x4c, 0x49, 0x05, 0x24, 0x00, 0x28, 0x60, 0x04, 0x41, 0x0d, 0x61, 0x48, 0x4c, 0x04, 0x41, 0x45, 0x20, 0x6c, 0x40, 0x20, 0x20, 0x29, 0x6c, 0x69, 0x41, 0x60, 0x64, 0x04, 0x41, 0x08, 0x20, 0x2c, 0x49, 0x05, 0x2c, 0x49, 0x48, 0x49, 0x49, 0x49, 0x0d, 0x20, 0x64, 0x49, 0x68, 0x25, 0x84, 0x6d, 0x78, 0x9d, 0x98, 0x68, 0x60, 0x60, 0x28, 0x60, 0x60, 0x68, 0x60, 0x04, 0x20, 0x29, 0x60, 0x24, 0x2d, 0x60, 0x24, 0x2d, 0x01, 0x24, 0xc7, 0xb4, 0xd9, 0x38, 0x6c }; 

and bring him out:

 for (int i = 0; i < 91; i++) { cout << hex << (int)a[i] << " "; } 

Displays most normal

  6c 40 20 20 29 6c 69 41 60 64 4 41 8 20 2c 49 5 2c 49 48 49 49 49 d 20 64 49 68 25 ffffff84 6d 78 ffffff9d ffffff98 68 60 60 28 60 60 68 60 4 20 29 60 24 2d 60 24 2d 1 24 ffffffc7 

But in some, for some reason, fffff is added to the beginning , how to solve this problem?

  • 2
    Change the array to 'unsigned char' - αλεχολυτ

3 answers 3

Depending on the compiler options, the char type can behave either as a signed char or as an unsigned char .

In your case, the char type behaves like the signed char type. As a result, characters that have a value of type 0x84 or 0x9d , that is, those characters that have values ​​greater than the maximum positive value that can be stored in an object of type signed char that is equal to the value. 127 , internally represented by negative numbers. Hence, when casting to type int their sign bit is replicated to the high bits of a number represented as an object of type int .

You should declare the array as having the unsigned char type, or when outputting to the console, cast the array characters explicitly to the unsigned char type.

Keep in mind that if you initialize an array using a list in curly brackets, the compiler will issue a diagnostic message that the value is narrowing, because, for example, the number 0x84 is a positive number that cannot be represented in the type signed char .

In the end, you have two approaches.

The first. Declare an array as having the type unsigned char And then there will be no problems.

The second. Having a character array of type char , output its elements using an explicit cast of the array characters to the type unsigned char .

Below is a program that demonstrates both approaches.

 #include <iostream> #include <iomanip> #include <cstring> int main() { const size_t N = 91; unsigned char a[N] = { 0x41, 0x0d, 0x61, 0x01, 0x60, 0x44, 0x69, 0x48, 0x24, 0x28, 0x60, 0x24, 0x2d, 0x2d, 0x41, 0x04, 0x4c, 0x49, 0x05, 0x24, 0x00, 0x28, 0x60, 0x04, 0x41, 0x0d, 0x61, 0x48, 0x4c, 0x04, 0x41, 0x45, 0x20, 0x6c, 0x40, 0x20, 0x20, 0x29, 0x6c, 0x69, 0x41, 0x60, 0x64, 0x04, 0x41, 0x08, 0x20, 0x2c, 0x49, 0x05, 0x2c, 0x49, 0x48, 0x49, 0x49, 0x49, 0x0d, 0x20, 0x64, 0x49, 0x68, 0x25, 0x84, 0x6d, 0x78, 0x9d, 0x98, 0x68, 0x60, 0x60, 0x28, 0x60, 0x60, 0x68, 0x60, 0x04, 0x20, 0x29, 0x60, 0x24, 0x2d, 0x60, 0x24, 0x2d, 0x01, 0x24, 0xc7, 0xb4, 0xd9, 0x38, 0x6c }; char b[N]; std::memcpy( b, a, N ); for ( size_t i = 0; i < N; i++ ) { std::cout << std::hex << std::setw( 2 ) << static_cast<int>( a[i] ); std::cout << ( ( i + 1 ) % 7 == 0 ? '\n' : ' ' ); } std::cout << std::endl; for ( size_t i = 0; i < N; i++ ) { std::cout << std::hex << std::setw( 2 ) << static_cast<int>( static_cast<unsigned char>( b[i] ) ); std::cout << ( ( i + 1 ) % 7 == 0 ? '\n' : ' ' ); } std::cout << std::endl; return 0; } 

Its output to the console looks like this.

 41 d 61 1 60 44 69 48 24 28 60 24 2d 2d 41 4 4c 49 5 24 0 28 60 4 41 d 61 48 4c 4 41 45 20 6c 40 20 20 29 6c 69 41 60 64 4 41 8 20 2c 49 5 2c 49 48 49 49 49 d 20 64 49 68 25 84 6d 78 9d 98 68 60 60 28 60 60 68 60 4 20 29 60 24 2d 60 24 2d 1 24 c7 b4 d9 38 6c 41 d 61 1 60 44 69 48 24 28 60 24 2d 2d 41 4 4c 49 5 24 0 28 60 4 41 d 61 48 4c 4 41 45 20 6c 40 20 20 29 6c 69 41 60 64 4 41 8 20 2c 49 5 2c 49 48 49 49 49 d 20 64 49 68 25 84 6d 78 9d 98 68 60 60 28 60 60 68 60 4 20 29 60 24 2d 60 24 2d 1 24 c7 b4 d9 38 6c 

    Lead not to int , but to unsigned char - this is the most correct decision, because when casting to int , sign-value comes into play, which you don’t need at all. The sizes of unsigned char and char same, so there will be no trouble.

      Remove the extra bits that are formed due to the sign (the char value is greater than CHAR_MAX perceived as negative with all the ensuing consequences):

       cout << hex << (int)(a[i] & UCHAR_MAX) << " "; 
      • The char character depends on the implementation. And that means the range of stored numbers. - αλεχολυτ
      • OK, UCHAR_MAX come down? - PinkTux
      • @wchar_t standard - user31238
      • @PinkTux Thought - but theoretically, if the car is a tricky idea, not based on the addition to two? The type of direct code? ... - Harry
      • @PinkTux my comment was about 127, not about the bitmask. The mask is also a curious question, already voiced by Harry. - αλεχολυτ