剛畢業找工作面試遇到這個問題,正確答案是“不一定,與編譯器相關”。這個結論是我在工作多年后才知道的。
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 };