隐式声明的函数返回的移位值产生错误结果
Bitshifting value returned by implicitly declared function producing wrong result
有两个函数返回相同的值。其中一个函数未声明。将两个值移位相同的常数会产生不同的结果。无法掌握下面发生的事情。有人可以提供一些光。这是代码
main.c
#include <stdio.h>
//unsigned int fun1();
unsigned int fun2()
{
return 3064476672;
}
int main() {
unsigned int b = fun1() >> 8;
printf("Bit shift result of function 1: %u, \n", b);
b = fun2() >> 8;
printf("Bit shift result of function 2: %u, \n", b);
}
func.c
unsigned int fun1()
{
return 3064476672;
}
结果 fun1
未声明
函数1的位移结果:4290160692,
函数2的位移结果:11970612,
fun1
声明的结果
函数1的位移结果:11970612,
函数2的位移结果:11970612,
程序有未定义的行为:
- 在C99及之后的版本中,由于调用了一个未声明的函数(实际上这是一个约束违规);
- 在 C89 中,由于调用了定义与
int f();
不兼容的未声明函数。
由于行为未定义,任何事情都可能发生——包括意外输出。
您的 C 实现使用 32 位 int
。当未声明 [=11=] 时,它假定 return 类型为 int
。 (这源于 C 语言历史,当时 int
是默认类型。当前的 C 标准不要求它。)
当实际 fun1
return 的 unsigned
值 3064476672 超出 int
范围时,您的 C 实现会将其解释为对应的 int
值 3064476672 − 232 = −1230490624。 (由于类型不匹配,C 标准未定义此行为。)
当您的 C 实现将此右移 8 位时,它会得到 −1230490624 / 256 = −4806604。 (负值的右移是实现定义的。编译器使用的算术移位很常见,它在右移时有效地复制二进制补码表示的符号位。)
当您将此 int
值传递给 printf
并要求它使用 %u
打印它时,printf
将 int
值解释为 −4806604相应的无符号值,−4806604 + 232 = 4290160692。(由于类型不匹配,%u
需要 unsigned
而你传递一个 int
,该行为未由 C 标准定义。)
虽然这实际上就是本例中发生的情况,但 C 标准并未定义该行为,因此不应依赖。
有两个函数返回相同的值。其中一个函数未声明。将两个值移位相同的常数会产生不同的结果。无法掌握下面发生的事情。有人可以提供一些光。这是代码
main.c
#include <stdio.h>
//unsigned int fun1();
unsigned int fun2()
{
return 3064476672;
}
int main() {
unsigned int b = fun1() >> 8;
printf("Bit shift result of function 1: %u, \n", b);
b = fun2() >> 8;
printf("Bit shift result of function 2: %u, \n", b);
}
func.c
unsigned int fun1()
{
return 3064476672;
}
结果 fun1
未声明
函数1的位移结果:4290160692,
函数2的位移结果:11970612,
fun1
声明的结果
函数1的位移结果:11970612,
函数2的位移结果:11970612,
程序有未定义的行为:
- 在C99及之后的版本中,由于调用了一个未声明的函数(实际上这是一个约束违规);
- 在 C89 中,由于调用了定义与
int f();
不兼容的未声明函数。
由于行为未定义,任何事情都可能发生——包括意外输出。
您的 C 实现使用 32 位 int
。当未声明 [=11=] 时,它假定 return 类型为 int
。 (这源于 C 语言历史,当时 int
是默认类型。当前的 C 标准不要求它。)
当实际 fun1
return 的 unsigned
值 3064476672 超出 int
范围时,您的 C 实现会将其解释为对应的 int
值 3064476672 − 232 = −1230490624。 (由于类型不匹配,C 标准未定义此行为。)
当您的 C 实现将此右移 8 位时,它会得到 −1230490624 / 256 = −4806604。 (负值的右移是实现定义的。编译器使用的算术移位很常见,它在右移时有效地复制二进制补码表示的符号位。)
当您将此 int
值传递给 printf
并要求它使用 %u
打印它时,printf
将 int
值解释为 −4806604相应的无符号值,−4806604 + 232 = 4290160692。(由于类型不匹配,%u
需要 unsigned
而你传递一个 int
,该行为未由 C 标准定义。)
虽然这实际上就是本例中发生的情况,但 C 标准并未定义该行为,因此不应依赖。