2

I have this very simple C++ code :

#include <iostream>
int main() {
    std::cout << (int)(char)(int)char(-2);
    return 0;
}

I am executing it on different setups :

  • Ubuntu 20.04 x64 (g++) -> Output : -2
  • Windows 10 x64 MSVC 2017 -> Output : -2
  • MacOS x64 Clang -> Output -2
  • Ubuntu Armv8 (g++) / EC2 Instance -> Output : 254

I want to obtain -2 all the time, and I don't understand this difference in behavior.

Does anyone have any idea?

BlackPopa
  • 163
  • 1
  • 11

3 Answers3

4

A compiler is allowed to choose if char is signed or unsigned. The standard says that they have to pick, but don't mandate which way they choose.

GCC supports -fsigned-char and -funsigned-char to force this behavior.

Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
3

From the ISO C++ International Standard (Tip of trunk):

§6.8.2 Fundamental Types

[basic.fundamental]

7 - Type char is a distinct type that has an implementation-defined choice of “signed char” or “unsigned char” as its underlying type.

[...]

Not much more to add about that.

Compiler vendors are free to choose whichever one they like or feel that is more reasonable given the target architecture, for ARM architectures it seems that unsigned char is preferred.

It appears that the reason behind this is the fact that older versions of ARM, prior to ARMv4, had no native support for loading halfwords and signed bytes, so char became unsigned by default, and unsigned it remains, for legacy reasons.

Main source:

http://www.davespace.co.uk/arm/efficient-c-for-arm/memaccess.html

anastaciu
  • 23,467
  • 7
  • 28
  • 53
0

The shown output is consistent with char being an unsigned data type on the platform in question. The C++ standard allows char to be equivalent to either unsigned char or signed char.

If you wish a specific behavior you can explicitly use a cast to signed char in your code.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148