1

I see a lot of code in C++ where they use char to represent numbers smaller than 256.

Should these be unsigned char instead of char?

What happens if I do this?

char t = 255;

I remember I read at some place that saying char is special about the signs.

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
WhatABeautifulWorld
  • 3,198
  • 3
  • 22
  • 30

4 Answers4

2

char is a distinct type from the signed and unsigned versions, and may be signed or unsigned. If you want a specifically signed or unsigned byte/char, you should indeed specify that in your variable declaration.

Mark B
  • 95,107
  • 10
  • 109
  • 188
2

Yes, char can be signed or unsigned [basic.fundamental], it's up to the compiler ("C++ implementation") to choose(*). If it's signed, there's no guarantee it can hold the value 255, and in the case it cannot hold the value 255, the conversion results in an implementation-defined value [conv.integral].

As unsigned char is guaranteed to have at least 8 bits (as well as char and signed char), the line unsigned char t = 255; is fine.

(*) That does not mean typedef signed char char;, as char, signed char and unsigned char are required to be three distinct types [basic.fundamental]/1.

dyp
  • 38,334
  • 13
  • 112
  • 177
0

Strictly speaking, it depends on how many bits there are in a char for the target in question. You're right that for a normal 2's complement machine with a signed 8-bit char type, that they should probably be using unsigned char.

The conversion from signed to unsigned, should one take place, is well-defined according to the C++ spec (4.7 Integral conversions):

2 If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —endnote]

The conversion from unsigned to signed, however, is implementation-defined:

3 If the destination type is signed, the value is unchanged if it can be represented in the destination type (and bit-field width); otherwise, the value is implementation-defined.

But in practice, most systems work they way you'd expect and things go fine. That is, signed overflow works like unsigned overflow, the bit patterns don't change regardless of signed->unsigned or unsigned->signed conversions, etc.

Carl Norum
  • 219,201
  • 40
  • 422
  • 469
0

The standard doesn't specify if plain 'char' is signed or unsigned. It's left up to the compiler. In GCC it's signed by default, but can be specified with -funsigned-char/-fsigned-char and likewise in MSVC the default is signed but can be forced to unsigned with /J.

Andrew
  • 638
  • 1
  • 6
  • 10
  • 1
    It's not correct. gcc will default char to signed or unsigned based on the target architecture/abi. On most, it will be signed. On others such as ppc (on most unices), it will be unsigned. – Guillaume May 30 '13 at 01:52