为啥在 printf() 调用中会遗漏逗号?
Posted
技术标签:
【中文标题】为啥在 printf() 调用中会遗漏逗号?【英文标题】:Why a comma can be missed in a printf() call?为什么在 printf() 调用中会遗漏逗号? 【发布时间】:2015-09-04 08:48:40 【问题描述】:我习惯于 C# 或 Java。
以下语句在 C 中怎么可能是正确的?
printf("aaa" "bbb");
在我的带有 GCC 4.9 的 Xubuntu 15.04 上。它输出:
aaabbb
正如我所尝试的,下面也可以!
CHAR *p = "aaa""bbb""ccc";
printf(p);
它输出:
aaabbbccc
我认为应该有一个逗号,但那样的话,第一个字符串将被视为格式字符串。那么,这种语法合法吗?
【问题讨论】:
这是连接两个字符串的语法。放置逗号将不起作用,因为它将被解释为两个不同的函数参数 见programmers.stackexchange.com/questions/254984/… C 中的"aaa" "bbb"
100% 等效于 Java "aaa" + "bbb"
。唯一的区别是 C 不会强迫你到处写 +
。
另见Why allow concatenation of string literals?
【参考方案1】:
是的,这是合法的语法,因为 ISO C99 中的翻译阶段 6,#5.1.1.2 翻译阶段:
连接相邻的字符串文字标记。
【讨论】:
这个最权威。【参考方案2】:如前所述,相邻的字符串由编译器连接。但是如果你想看到一些不同,你可以在你的字符串中添加一个 \0
空终止符。
在添加 aaa\0
时,您的 o/p 将只是 aaa
,因为 printf 将打印直到找到第一个 \0
空终止符。
#include<stdio.h>
int main()
printf("aaa\0" "bbb");
输出
aaa
【讨论】:
我知道 '\0' 在 C 中被视为字符串的结束符号。但是我是否需要将其显式添加到字符串的末尾?喜欢这个"aaa\0"
?
嗯...非常明确! "aaa""bbb\0""ccc"
输出 aaabbb
。但我认为编译器仍然会生成aaabbb\0ccc\0
。但是printf()
在第一个 `\0' 处停止。
你不需要自己添加,编译器会为你添加,但只有当它意识到字符串已经结束时,所以 char* s = "as" 将被编译器以空终止,但是 char* q = "as" "ca" 只会在 "ca" 之后为空终止
@CIsForCoocckies 我同意编译器默认为您添加它,但 printf 一直执行到第一个 \0
@smwikipedia 同意你的看法【参考方案3】:
这两个字符串只是由编译器连接起来的。
【讨论】:
【参考方案4】:当编译器看到两个连续的字符串 literals 时,它会将它们连接起来(在编译器的解析时),就像您观察到的那样。这对非文字不起作用(编译器语法错误)。
comma operator 与串联无关。它首先计算左边的操作数,然后是右边的,并丢弃左边的结果,给出右边的结果。它对副作用很有用(例如 Lisp 中的 progn
、Ocaml 中的 ;
、Scheme 中的 begin
)。当然,逗号也用于分隔调用中的参数。
【讨论】:
【参考方案5】:正如@Jens 所说,相邻的字符串文字由编译器连接。
这样做的一个原因是您可以像这样进行预处理器:
#include <stdio.h>
#if defined(__linux__)
#define MY_OS "linux"
#elif defined(_WIN32)
#define MY_OS "windows"
#else
#define MY_OS "probably something BSD-derived"
#endif
int main(void)
printf("my os is " MY_OS "\n");
这样可以为大家节省很多时间。
【讨论】:
我不确定这是主要原因。可能,主要原因是能够在不使用反斜杠的情况下输入很长的多行字符串常量。 @BasileStarynkevitch 是的,我并不是要暗示这是唯一的原因:L以上是关于为啥在 printf() 调用中会遗漏逗号?的主要内容,如果未能解决你的问题,请参考以下文章