从签名字符到int类型的C类型转换

时间:2017-03-09 17:30:37

标签: c char signed

在下面的代码段中,输出不应该是1吗?为什么我输出为-1和4294967295? 我理解的是,变量c,这里是带符号的类型,所以它的值不应该是1?

char c=0xff;
printf("%d %u",c,c);

4 个答案:

答案 0 :(得分:1)

c是签名类型。 char是8位。所以你有一个8位有符号数,所有位1.在二进制补码机器上,它的计算结果为-1。

当你做那种事情时,有些编译器会警告你。如果您正在使用gcc / clang,请启用所有警告。

Pedant note:在某些机器上它的值可能是255,如果编译器处理' char'没有签名。

答案 1 :(得分:0)

你得到了正确答案。

%u格式说明符表示该值为unsigned int。编译器会自动将您的8位char提升为32位int。但是,您必须记住char是签名类型。所以0xff的值实际上是-1。

当从char转换为int时,该值仍为-1,但它是32位表示,二进制为11111111 11111111 11111111 11111111或十六进制{{1 }}

如果将其解释为无符号整数,则显然会保留所有位,因为长度相同,但现在将其作为无符号数量处理。

0xffffffff

答案 2 :(得分:0)

C中有三种字符类型,charsigned charunsigned char。简单charsigned charunsigned char具有相同的表示形式;选择是实现定义的。您的实施中似乎已签署了简单char

所有三种类型都具有相同的大小,可能 8位(CHAR_BIT,在<limits.h>中定义,指定一个字节中的位数)。我假设8位。

char c=0xff;

假设普通char已签名,则值0xff255)超出类型char的范围。由于您无法将值255存储在char对象中,因此会隐式转换该值。此转换的结果是实现定义的,但很可能是-1

请谨记这一点:0xff只是写255的另一种方式,0xff-1是两个不同的值。您无法将值255存储在char对象中;它的值是-1。整数常量,无论是十进制,十六进制还是八进制,都指定值,而不是表示。

如果您确实需要值为0xff的单字节对象,请将其定义为unsigned char,而不是char

printf("%d %u",c,c);

当一个比int更窄的整数类型的值传递给printf(或任何可变函数)时,如果该类型可以保存该类型的整个范围,它将被提升为int值,或unsigned int如果不能。对于char类型,它几乎可以肯定地提升为int。所以这个电话相当于:

printf("%d %u", -1, -1);

"%d"格式的输出很明显。 "%u"的输出不太明显。 "%u"告诉printf相应的参数类型为unsigned int,但您传递的值为int可能发生的是int值的表示被视为,就像类型为unsigned int一样,最有可能产生UINT_MAX },恰好是您系统上的4294967295。如果您确实想这样做,则应值转换为unsigned int类型。这样:

printf("%d %u", -1, (unsigned int)-1);

定义明确。

你的两行代码正在玩各种类型的游戏,将一种类型的值视为另一种类型,并进行隐式转换,这些转换可能产生实现定义的结果和/或取决于你的编译器碰巧做出的选择。

无论你想做什么,毫无疑问都是一种更简洁的方法(除非你只是试图看看你的实现对这个特定代码的作用)。

答案 3 :(得分:0)

让我们从使用OP的“c,这里是签名类型”

的假设开始
char c=0xff;  // Implementation defined behavior.

0xff是一个十六进制常量,其值为255,类型为int

  

...新类型已签名且值无法在其中表示;结果是实现定义的,或者引发实现定义的信号。 §6.3.1.43

因此,c的值是实现定义的(ID)。让我们假设8位环绕的公共ID行为,因此c - &gt; -1

签名char将被提升为int,因为printf("%d %u",c,c);的可变参数的一部分与printf("%d %u",-1, -1);相同。使用-1打印"%d"不是问题,并且会打印"-1"

使用int -1打印"%x"是未定义的行为(UB),因为它是不匹配的说明符/类型,并且不属于在两种类型中都可表示的例外。常见的UB是打印值,就像它在传递之前被转换为unsigned一样。当UINT_MAX == 4294967295(4字节)将值打印为-1 + (UINT_MAX + 1)或“4294967295”时。

因此,使用ID和UB,您会得到一个结果,但强大的代码将被重写,以便两者都不依赖。