我正在阅读这本书" C编程语言"作者:Brian Kernighan和Dennis Ritchie(第2版,PHI出版)。在第一章的第一篇 1.1入门 A Tutorial Introduction ,第7页,他们说必须在printf()参数中使用\n
否则C编译会产生错误信息。但是当我在printf()中编译没有\n
的程序时,它很好。我没有看到任何错误消息。我正在使用Dev-C便携式和#34; MinGW GCC 4.6.2 32位"编译器。
为什么我没有收到错误消息?
答案 0 :(得分:9)
以下是K& R第二版第7页的问题:
您必须使用
那样的话\n
在printf
参数中包含换行符;如果你尝试像printf("hello, world ");
C编译器将产生错误消息。
这意味着您无法在带引号的字符串中嵌入文字换行符。
然而,下面的任何一行都没问题:
printf("hello, world"); /* does not print a newline */
printf("hello, world\n"); /* prints a newline */
上面的所有文字都说你不能在源代码中包含跨越多行的带引号的字符串。
您还可以使用反斜杠转义换行符。 C预处理器将删除反斜杠和换行符,因此以下两个语句是等效的:
printf("hello, world\
");
printf("hello, world");
如果你有很多文本,你可以将多个引用的字符串放在一起,或者用空格分隔,编译器会为你加入它们:
printf("hello, world\n"
"this is a second line of text\n"
"but you still need to include backslash-n to break each line\n");
答案 1 :(得分:3)
您没有收到编译时错误消息,因为没有错误。
在第一篇文章中,他们说必须在
\n
参数中使用printf()
,否则C编译器将产生错误消息。
您能否(按部分和/或页码)引用该声明的位置?我真的不相信K& R(你正在使用第二版,对吗?)说。如果它确实这么说,那就是书中的错误。
更新:本书的内容非常正确地说,字符串文字中的换行符由双字符序列\n
表示,而不是由实际的换行符表示。字符串文字必须位于单个逻辑源行上;
printf("hello
world");
是语法错误。这适用于所有字符串文字,无论它们是否为printf
格式字符串。
字符串文字中的实际换行符是错误。 表示换行符的\n
序列是可选的;它缺少不是错误,但printf
格式字符串通常以\n
结尾。
printf
调用不需要包含\n
字符,我从未见过编译器抱怨缺少printf
的{{1}}。
此处存在问题,但这不是编译时错误。
一些例子:
\n
这是完全合法的电话。它在标准输出上打印指定的字符串,不带换行符。
printf("No newline");
格式字符串中没有printf("hello%c", '\n');
,但它会打印\n
后跟换行符。再次,这是完全合法的。
实际问题是你应该(几乎)总是在输出的最后打印换行符。这个完整的计划:
hello
是合法的,但在某些实现中,其行为可能未定义。相关规则在标准7.21.2第2节(引用来自N1570 draft)中:
文本流是由字符组成的有序字符序列 行,每行由零个或多个字符加上a组成 终止换行符。最后一行是否需要 终止换行符是实现定义的。
是否需要终止换行符,使用换行符结束输出(几乎总是)是一个非常好的主意。如果我在我的系统上运行它,我会立即获得字符串#include <stdio.h>
int main(void) {
printf("hello");
return 0;
}
,然后在同一行上显示我的shell提示符。这不违法,但不方便和丑陋。
但这只适用于程序输出的最后。该程序完全有效,并具有明确定义的行为:
hello
尽管如此,生成干净输出的最简单,最可靠的方法是每次#include <stdio.h>
int main(void) {
printf("hello");
putchar('\n');
return 0;
}
调用只打印一行,结果只有一个printf
个字符。这不是普遍的规则;有时,一次打印一条线或者在一个'\n'
中打印两条或更多条线是方便的。
答案 2 :(得分:2)
通常情况下,如果您不使用printf
结束\n
格式字符串,则部分输出会保留在stdout
buffer中,而您我需要调用fflush
来显示所有输出。
这意味着如果您没有获得所有预期的输出,则应在适当的位置添加fflush
(例如在调用fork
之前)。
但是在这种情况下你不会得到编译器消息,因为它不是错误(可能是许多初学者正在做的错误)。如果您真的想要,可以自定义编译器(例如,如果使用最新的MELT编译器,则使用GCC)来获取警告。我认为不值得付出努力(因为合法调用printf
而没有任何\n
....)
如果您使用(递归)函数编码(递归)函数以从其AST输出表达式,则合法printf
调用而不使用换行符的示例你当然应该不在每个令牌后发出换行符。
请参阅printf(3),fflush(3),stdio(3),setvbuf(3)等文档...