C/C++的char是有符号还是无符号

刚毕业找工作面试遇到这个问题,正确答案是“不一定,与编译器相关”。这个结论是我在工作多年后才知道的。

C/C++标准中列出了三种类型:(plain) char, signed char 和 unsigned char。第一种就是普通的char不加前缀,实际对应后两种实现的其中一种,取决于编译器,有的甚至提供编译选项指定是否有符号。从经验看,我猜测大多数都是对应signed有符号的版本。

可以参考C99标准N1256的6.2.5.15一节:

The three types char, signed char, and unsigned char are collectively called
the character types. The implementation shall define char to have the same range,
representation, and behavior as either signed char or unsigned char.

以及C++11标准N3242的3.9.1.1一节:

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.

与char不同的是,int在C标准中明确指出是有符号的,size_t是无符号的。

对于原先的问题,其实换一个问法更好:如何通过代码验证char是否有符号?

下面是一个简单实现:

 1 #include <iostream>
 2 
 3 template<class T> bool isSigned() { return (T)-1 < (T)0; }
 4 
 5 int main()
 6 {
 7     std::cout << isSigned<char>() << std::endl;
 8     std::cout << isSigned<signed char>() << std::endl;
 9     std::cout << isSigned<unsigned char>() << std::endl;
10     return 0;
11 }

我在Windows上用g++编译的程序输出是1 1 0.

其实std::is_signed也正是这么实现的。例如VC++的源码:

    // TEMPLATE CLASS is_signed
template<class _Ty>
    struct _Has_signed_vals
        : _Cat_base<(typename remove_cv<_Ty>::type)(-1)
        < (typename remove_cv<_Ty>::type)(0)>
    {    // integral type can represent negative values
    };

template<class _Ty>
    struct is_signed
        : _Cat_base<is_floating_point<_Ty>::value || (is_integral<_Ty>::value
        && _Has_signed_vals<
            typename _If<is_integral<_Ty>::value, _Ty, int>::type>::value)>
    {    // determine whether _Ty is a signed type
    };

 

posted @ 2020-07-05 17:18  Xrst  阅读(1932)  评论(0编辑  收藏  举报