Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

char!=(signed char), char!=(unsigned char)

Tags:

c++

char

The code below compiles, but has different behavior for the char type than for the int types.

In particular

   cout << getIsTrue< isX<int8>::ikIsX  >() << endl;    cout << getIsTrue< isX<uint8>::ikIsX  >() << endl;    cout << getIsTrue< isX<char>::ikIsX  >() << endl; 

result in 3 instantiations of templates for three types: int8, uint8 and char. What gives?

The same is not true for ints: int and uint32 which result in the same template instantiation, and signed int another.

The reason seems to be that C++ sees char, signed char and unsigned char as three different types. Whereas int is the same as a signed int. Is this right or am I missing something?

#include <iostream>  using namespace std;  typedef   signed char       int8; typedef unsigned char      uint8; typedef   signed short      int16; typedef unsigned short     uint16; typedef   signed int        int32; typedef unsigned int       uint32; typedef   signed long long  int64; typedef unsigned long long uint64;  struct TrueType {}; struct FalseType {};  template <typename T> struct isX {    typedef typename T::ikIsX ikIsX; };   // This  int==int32 is ambiguous //template <>            struct isX<int  >    { typedef FalseType ikIsX; };  // Fails template <>            struct isX<int32  >  { typedef FalseType ikIsX; }; template <>            struct isX<uint32 >  { typedef FalseType ikIsX; };   // Whay isn't this ambiguous? char==int8 template <>            struct isX<char  >  { typedef FalseType ikIsX; }; template <>            struct isX<int8  >  { typedef FalseType ikIsX; }; template <>            struct isX<uint8 >  { typedef FalseType ikIsX; };   template <typename T> bool getIsTrue(); template <>           bool getIsTrue<TrueType>() { return true; } template <>           bool getIsTrue<FalseType>() { return false; }  int main(int, char **t ) {    cout << sizeof(int8) << endl;  // 1    cout << sizeof(uint8) << endl; // 1    cout << sizeof(char) << endl;  // 1     cout << getIsTrue< isX<int8>::ikIsX  >() << endl;    cout << getIsTrue< isX<uint8>::ikIsX  >() << endl;    cout << getIsTrue< isX<char>::ikIsX  >() << endl;     cout << getIsTrue< isX<int32>::ikIsX  >() << endl;    cout << getIsTrue< isX<uint32>::ikIsX  >() << endl;    cout << getIsTrue< isX<int>::ikIsX  >() << endl;  } 

I'm using g++ 4.something

like image 518
user48956 Avatar asked Jan 12 '09 18:01

user48956


People also ask

What are signed char and unsigned char?

A signed char is a signed value which is typically smaller than, and is guaranteed not to be bigger than, a short . An unsigned char is an unsigned value which is typically smaller than, and is guaranteed not to be bigger than, a short .

What is meant by signed and unsigned char in C?

The term "unsigned" in computer programming indicates a variable that can hold only positive numbers. The term "signed" in computer code indicates that a variable can hold negative and positive values. The property can be applied to most of the numeric data types including int, char, short and long.

Is char the same as signed char?

By the C++ standard, a signed char is guaranteed to be able to hold values -127 to 127 (not -128!), whereas a unsigned char is able to hold values 0 to 255.

Why there is signed and unsigned char?

An unsigned type can only represent postive values (and zero) where as a signed type can represent both positive and negative values (and zero). In the case of a 8-bit char this means that an unsigned char variable can hold a value in the range 0 to 255 while a signed char has the range -128 to 127.


2 Answers

Here is your answer from the standard:

3.9.1 Fundamental types [basic.fundamental]

Objects declared as characters (char) shall be large enough to store any member of the implementation's basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementation-defined whether a char object can hold negative values. Characters can be explicitly declared unsigned or signed. Plain char, signed char, and unsigned char are three distinct types. A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (basic.types); that is, they have the same object representation. For character types, all bits of the object representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types. In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined.

like image 66
Greg Rogers Avatar answered Oct 25 '22 07:10

Greg Rogers


While most integral types like short and int default to being signed, char does not have a default signage in C++.

It is neither the type signed char nor unsigned char, so implementations may decide whether it is signed.

It's a common mistake that C++ programmers run into when they use char as an 8 bit integer type.

like image 33
Drew Dormann Avatar answered Oct 25 '22 06:10

Drew Dormann