13

我忘记将随附的变量添加到 printf() 调用中。printf() 如何知道我想打印什么?

int successful = 0;//Flag
printf("\nEnter a number to search for: ");
scanf("%d", &data);
successful = search(list, data);
successful? printf("\n'%d' was found\n\n", data) : printf("\n'%d' was NOT found\n\n");

有问题的代码是最后一行三元表达式的最后一个“else”。我已经运行了几十次,它似乎总是在输出中打印正确的参数。

: printf("\n'%d' was NOT found\n\n");

每次这仍然如何工作?

4

2 回答 2

19

它可能看起来有效,但不要依赖于此。

它可能有效,因为您最近的函数调用,

successful = search(list, data);

将值留在堆栈data上的适当位置。


在这里提一下,如果您忽略在声明单个局部变量的函数中包含 return 语句,有时会发生类似的意外情况可能会很有用。

int wowee () {
    int val;
    val = 12;

    // <-- no return statement!
}

val有时,会返回局部变量,可能是由于同一种堆栈重用。但这也是未定义的行为,即使它碰巧起作用。


这两种情况的寓意是启用更多的编译器警告。编译器可以诊断此类问题,甚至检查格式字符串是否与传递给 prinf -family 函数的变量类型匹配

于 2013-09-17T04:31:20.093 回答
12

哎呀!那就是“未定义的行为”。

printf("\n'%d' was NOT found\n\n"); // undefined behavior

“未定义的行为”是一个技术术语,基本上意味着......任何事情都可能发生。也许正确的事情会发生,也许程序会崩溃,或者它会完全做其他事情。

在这种情况下,也许你想要的值已经在堆栈中的正确位置,所以当printf()获取它的参数时,它得到了正确的值。这在很大程度上取决于优化的使用和您正在使用的特定 ABI,特别是,并非所有 ABI 都将值放在堆栈上以进行非可变函数调用。

successful = search(list, data);
//                        ^^^^ places "data" on stack as second argument

如果您将程序编译为 64 位,它可能不再工作,因为最常见的 x64 ABI 使用寄存器作为前四个非可变参数。

它不会改变您的代码错误的事实,如果您想始终如一地获得正确答案,则需要修复它。

于 2013-09-17T04:31:12.930 回答