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

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 打印它时,printfint 值解释为 −4806604相应的无符号值,−4806604 + 232 = 4290160692。(由于类型不匹配,%u 需要 unsigned 而你传递一个 int,该行为未由 C 标准定义。)

虽然这实际上就是本例中发生的情况,但 C 标准并未定义该行为,因此不应依赖。