由隐式声明的函数返回的位移值产生错误的结果

时间:2019-12-31 06:27:22

标签: c function-declaration

两个函数返回相同的值。函数之一是未声明。将两个值都移位相同的常数会产生不同的结果。无法掌握下面发生的事情。有人可以提供一些照明。这是代码

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,

2 个答案:

答案 0 :(得分:2)

程序具有未定义的行为:

  • 在C99和更高版本中,由于调用了未声明的函数(实际上这是违反约束的行为);
  • 在C89中,由于调用了一个未声明的函数,该函数的定义与int f();不兼容。

由于行为是不确定的,所以任何事情都可能发生-包括意外的输出。

答案 1 :(得分:0)

您的C实现使用32位int。如果未声明fun1,则假定返回类型为int。 (这源于C语言历史,当时int是默认类型。当前的C标准未要求使用它。)

当实际的fun1返回unsigned范围之外的int值3064476672时,您的C实现会将其解释为相应的int值3064476672- 2 32 = -1230490624。 (由于类型不匹配,因此行为不是C标准定义的。)

当您的C实现将此右移8位时,其值为−1230490624 / 256 = −4806604。 (负值的右移是实现定义的。编译器使用的算术移位很常见,该算术移位可在右移时有效地复制两个补码表示的符号位。)

当您将此int值传递给printf并要求它以%u打印时,printf会将int值−4806604解释为无符号值,−4806604 + 2 32 =4290160692。(由于类型不匹配,当%u要求unsigned传递int时,行为不是C标准定义的。)

虽然这实际上是在这种情况下发生的情况,但是该行为不是C标准定义的,因此不应依赖。