为什么修改版的“Hello, world!” Effective C 一书中的程序使用 `printf` 工作?

问题描述 投票:0回答:2

我已经开始学习用 C 编程。我已经开始阅读 Seacord 的 Effective C 书,我已经在第 6 页感到困惑=D
在本书的前面,有一个小程序,他称之为“Hello, world!”的修订版。程序:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    if (puts("Hello, world!") == EOF) {
        return EXIT_FAILURE;
        // code here never executes
    }
    return EXIT_SUCCESS;
    // code here never executes
}

它按预期对我有用。然后 Seacord 在以以下段落结尾的部分中介绍了

printf
功能:

输出字符串最简单的方法是使用

puts
函数,如前所示。如果您确实在“Hello, world!”的修订版中使用
printf
而不是
puts
程序,你会发现它不再有效,因为
printf
函数返回的状态与
puts
函数不同。
printf
函数如果成功则返回打印的字符数,如果发生输出或编码错误则返回负值。您可以尝试修改“Hello, world!”程序使用
printf
函数作为练习。

刚读完就已经很困惑了,因为早些时候他写道:

puts
函数如果发生写入错误,返回宏
EOF
(一个负整数)的值;否则,它返回一个非负整数值。

基于这些段落,我看不出函数返回状态之间的相关差异。不管怎样,我试过这个程序:

#include <stdio.h>
#include <stdlib.h>
int main(void) {
    if (printf("%s\n", "Hello, world!") == EOF) {
        return EXIT_FAILURE;
        // code here never executes
    }
    return EXIT_SUCCESS;
    // code here never executes
}

它奏效了。我还在 https://godbolt.org/ 上尝试了多个编译器和版本,并且每次都有效,尽管我认为我还没有使用这个工具的经验。
我的问题是:在这个例子中什么不应该起作用?

在我的电脑上我使用

  • Windows 10 家庭版 10.0.19045 build 19045
  • Microsoft Visual Studio Community 2022(64 位)版本 17.5.1
  • 微软 Visual C++ 2022 00482-90000-00000-AA637
  • Microsoft C/C++ 优化编译器版本 19.35.32215 for x64

我在 VS 2022 的 x64 本机工具命令提示符中使用了以下命令:

cl /std:c17 filename.c

(我很抱歉写了这么多细节,但我还不知道什么对你很重要。我欢迎任何关于在未来的问题中提供什么信息的建议。)

c printf puts
2个回答
3
投票

不同之处在于函数

puts
在出错的情况下返回
EOF
,而函数
printf
在出错的情况下返回负值(不一定等于
EOF
)。

来自C标准(7.21.7.9 The puts function)

3 如果发生写入错误,puts函数返回EOF;否则它 返回一个非负值。

和(7.21.6.3 printf 函数)

3 printf函数返回传输的字符数,或者 如果发生输出或编码错误,则为负值.

所以这个条件调用

printf

if (printf("%s\n", "Hello, world!") == EOF)

即使发生错误也可以评估为 false。

对于

printf
你应该写

if (printf("%s\n", "Hello, world!") < 0 )

1
投票

在这个例子中什么不应该工作?

printf()
被记录为在失败时返回 negative value负数不必与
EOF
相同。

printf()
的返回值与
EOF
进行比较是错误的,因为如果
printf()
失败,并且它的返回值恰好与
EOF
相同,程序将继续执行代码退出,如果应用程序认为失败
printf()
是致命错误,这可能会导致一些大问题。

puts()
printf()
之间的主要区别在于,在失败时,前者返回
EOF
,而后者返回负值

正如@Marco 评论的那样,检查

printf()
的返回值(在大多数情况下)并尝试使用
stderr
/
fprintf
打印诊断消息给
fputs()
是没有意义的,因为无法保证后续调用会成功并且诊断消息会像这样永远持续下去:

if (printf ("Hello World.\n") < 0) { 
    if (fprintf (stderr, "printf() failed.\n") < 0) {
        if (fprintf (stderr, "fprintf() failed.\n") {
          /* This goes infinitely. */
© www.soinside.com 2019 - 2024. All rights reserved.