类型“int”或“long”、“char”等是否总是在 C 和 C++ 中签名?

Are types 'int' or 'long', 'char', etc. always signed in C and C++?

提问人:KiWon Lee 提问时间:6/23/2023 最后编辑:chqrlieKiWon Lee 更新时间:6/24/2023 访问量:180

问:

我一直都知道,当我在 C 和 C++ 开发中使用 or 、 、 等时,我已经对值进行了签名。顺便说一句,根据编译器或操作系统的不同,当这些类型的默认有符号变为无符号时会发生什么?我正在询问,因为我从未在论文或书籍中看到过对此的提及,而且我不知道。intlongcharshort

C++ C 无符号 签名

评论

3赞 Vlad from Moscow 6/23/2023
什么是“默认值”?不清楚你在问什么。
3赞 Vlad from Moscow 6/23/2023
@MarcoBonelli字符不是有符号类型。
3赞 Alan Birtles 6/23/2023
默认情况下,整数类型是有符号的,只有字符类型未指定 en.cppreference.com/w/cpp/language/types
8赞 Richard Critten 6/24/2023
char可以是 OR(实现定义),并且是与 和 不同的类型;请参阅字符类型signedunsignedunsigned charsigned char
3赞 HolyBlackCat 6/24/2023
char在某些平台上可以取消签名,但通常是签名的。其他一切都已签名。

答:

5赞 chqrlie 6/24/2023 #1

类型 、 和 都是有符号的,除非显式限定为 。请注意,和 实际上是限定符本身,如果省略,则类型是隐式的。shortintlonglong longunsignedshortlongint

类型是特殊的:它不同于类型,显然是有符号的,而类型则不是。根据平台和编译器设置,类型可以是有符号的,也可以是无符号的。您可以通过比较 中定义的宏的值来测试这一点,或者通过强制转换为并测试它是否保持负值来测试它。charsigned charunsigned charcharCHAR_MIN<limits.h>0-1(char)

#include <limits.h>
#include <stdio.h>

int main(void) {
    if ((char)-1 < 0) {
        /* most common case */
        printf("char is signed, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
    } else
    if (sizeof(char) == sizeof(int)) {
        /* corner case, for some DSP systems */
        /* char type is the same as unsigned int */
        printf("char is unsigned, range is %u..%u\n", CHAR_MIN, CHAR_MAX);
    } else {
        /* common case, enabled with -funsigned-char for gcc and clang */
        /* char values and constants will promote to int */
        printf("char is unsigned, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
    }
    return 0;
}

请注意,不能使用上述测试进行预处理,但可以在预处理器表达式中使用中定义的常量:<limits.h>

#include <limits.h>
#include <stdio.h>

int main(void) {
#if CHAR_MIN < 0
    printf("char is signed, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
#elif CHAR_MAX == UINT_MAX
    printf("char is unsigned, range is %u..%u\n", CHAR_MIN, CHAR_MAX);
#else
    printf("char is unsigned, range is %d..%d\n", CHAR_MIN, CHAR_MAX);
#endif
    return 0;
}

这在 C++ 中也有效,但有一种更惯用的方法来测试它。std::is_signed_v<char>

评论

0赞 HolyBlackCat 6/24/2023
或。std::is_signed_v<char>
0赞 chqrlie 6/24/2023
@HolyBlackCat:当然,答案修改了。
0赞 pts 6/24/2023
...或(char)-1 < (char)0
0赞 chux - Reinstate Monica 6/24/2023
@chqrlie 极端情况:对于那些讨厌的宽,需要 when 是无符号的。charint/unsignedprintf(", range is %d..%d\n", CHAR_MIN, CHAR_MAX);printf(", range is %u..%u\n", CHAR_MIN, CHAR_MAX);char
1赞 chqrlie 6/25/2023
警告:语言律师口语。 可以表示为 ,但它的类型可能是在病理情况下,其中 是无符号的 和 。在 C17 之前,传递 for 是未定义的行为,如果该值仅在 C23 之前在两种类型中都可以表示,则进行定义。这种变化植根于常识,但来得有点晚。for 的情况有所不同,但更具说服力,因为该行为在 C17 下和之前未定义,适用于所有其他架构。CHAR_MINintunsigned intcharsizeof(unsigned) == 1unsigned int%d%uCHAR_MAX