请帮我区分C:
中的这些代码代码1:
#include<stdio.h>
#include <stdint.h>
uint8_t fb(int a)
{
return -3;
}
int main()
{
int a = fb(-3);
printf("%d",a);
return 0;
}
代码2:
#include<stdio.h>
unsigned int fb(int a)
{
return -3;
}
int main()
{
int a = fb(-3);
printf("%d",a);
return 0;
}
问题是第一个代码按预期返回253但第二个代码返回-3,这是意外的,因为返回类型是无符号的。请帮助我如何做到这一点?
我使用过mingw gcc编译器。
答案 0 :(得分:9)
在第一个程序中,
int
-3(FFFFFFFD)被强制转换为uint8_t
为253(FD)。高阶字节被丢弃,因此它适合。uint8_t
253(FD)通过符号扩展名转换为int
至253(000000FD)。在第二个程序中,
int
-3(FFFFFFFD)强制转换为unsigned int
4294967293(FFFFFFFD)。没有字节需要删除。unsigned int
4294967293(FFFFFFFD)强制转换为int
为-3(FFFFFFFD)。注意:
答案 1 :(得分:2)
从已签名到无签名的转换将遵循6.3.1.3
draft C99 standard的有符号和无符号整数部分中规定的规则,其中包含:
否则,如果新类型是无符号的,则转换为 重复加或减一个以上的最大值 可以用新类型表示,直到值在范围内 新类型。 49)
因此,这意味着-3
将通过向值添加UMAX +1
来转换为uint8_t
。在253
的情况下,这是一个相对较小的值std::numeric_limits<unsigned int>::max() + 1 - 3
,它适合 singed int ,因此可以毫无问题地转换为 signed int 。
在第二种情况下, unsigned int 的返回值,转换后我们将得到一个相当大的值,实际上是6.5
。哪个不适合 signed int 这是溢出的,因此根据{em> 5 部分的{{1}}段说明未定义的行为:
如果在评估过程中出现异常情况 表达式(即,如果结果未在数学上定义或 不在其类型的可表示值的范围内),行为 未定义。
答案 2 :(得分:0)
从积分类型转换为无符号整数类型的规则很简单:
根据需要添加/下接(目标类型的最大值+ 1)。
从积分型转换为signd积分型的规则仍然比较简单:
保留该值,如果超出范围,则转换未定义
大多数现代实现(都在Windows平台上)定义它以相应的unsigned
类型添加/减去相同的常量,直到它适合。
使用这些规则,第一个示例中从fb()
返回的转换是保值并且确定:
-3 - &gt; 256-3 = 253 - &gt; 253
第二个例子中的返回是超出范围的,因此是未定义的行为,但通常是:
-3 - &gt; 2 CHAR_BIT * sizeof(int) -3 - &gt; -3
奖金事实:
CHAR_BIT
是一个预处理器常量,给出一个字节的位数。sizeof
是一个运算符,它给出了类型/变量中的字节数。答案 3 :(得分:0)
unsigned int应打印为%u
而不是%d