在C中打印时有符号和无符号字符的行为

时间:2015-08-01 06:04:04

标签: c

我在Windows 7上的Code :: Blocks 10.05中编译了以下C程序。

int main()
{
    unsigned char a=-5;
    signed char b=-5;
    char c=-5;
    printf("%d  %d  %d \n",a,b,c);
    printf("%u  %u  %u \n",a,b,c);
}

我期待以下输出

251 -5 -5
251 251 251

我的理由是这样的,

-5在2的补语表示中表示为1111 1011。 因此将打印251。

但我得到了以下输出。

251 -5 -5 
251 4294967291 4294967291

我知道4294967291是-5位的32位2的补码表示。

但为什么unsigned char a打印为251而不是4294967291?

4 个答案:

答案 0 :(得分:4)

printf是一个可变函数,它导致(感谢@TheParamagneticCroissant进行校正)将整数参数提升为int或unsigned int。根据标准促销规则将签署适当的扩展。这导致您获得的数字是此促销过程后的结果。

相反,您可以使用"%" PRIu8打印8位无符号和"%" PRId8来打印8位有符号数。但请注意,参数仍将被提升,然后printf将根据格式说明符再次向下转换它们,这可能仍然会改变该值,但我不确定它是否来自内存。

此外,C不能保证char为8位,最好包含<stdint.h>标头并使用正确的固定宽度类型。

您的代码的固定版本如下:

#include <stdint.h>
int main()
{
    uint8_t a=-5;
    int8_t b=-5;
    printf("%" PRId8 "%" PRId8 "\n", a, b);
    printf("%" PRIu8 "%" PRIu8 "\n", a, b);
}

注意我没有包含等效的char,因为所有固定宽度类型都是已定义的符号,因此没有直接等效的char,它具有未定义的签名。

答案 1 :(得分:2)

unsigned整数类型(包括unsigned char)使用模运算。对于unsigned char,它是模UCHAR_MAX + 1,其中UCHAR_MAX<limits.h>中实现定义的值,具有典型值,大多数实现为255({{ 1}}也是标准允许255)的最小值。将UCHAR_MAX添加到256(即在-50之间获得余数以便在代码中初始化255)将解释为什么{{1} }的值为a

至于为什么任何值都在打印时,这些值在传递给a时会被提升为251类型。此促销与您的格式字符串无关,但是int格式说明符所需的内容,因此值将打印出来。

答案 2 :(得分:1)

@Vality的回答有点不对劲。由于unsigned char必须保存最多至少255的值,因此如果uint8_t存在,CHAR_BIT必须为8。

没有理由使用讨厌的PRI宏,只需使用它:

unsigned char a = -5;
signed char b = -5;
char c = -5;

printf("%hhd  %hhd  %hhd \n", a, b, c);
printf("%hhu  %hhu  %hhu \n", a, b, c);

答案 3 :(得分:0)

因为a包含值251,而不是值-5