我认为可以使用一个且只引用一个字符串来初始化C字符串。我只是想知道这是怎么回事?
char const help_message [] =
"Usage: %s [options] files ...\n"
"\n"
"Options include:\n"
" --verbose -v Be verbose\n"
" --help -h Print this help message\n"
" --output -o Specify output file\n"
"\n" ;
printf (help_message, argv [0]) ;
答案 0 :(得分:12)
compiler会自动连接相邻的字符串。
这对于提高可读性非常有用,如您的示例或某些预处理器函数:
#define LOG(x) printf("%s", "Logging: " x)
LOG("HeyHey");
非常人为的例子,但是明白了这一点。
答案 1 :(得分:2)
因为编译器认为相邻的引用字符串是同一字符串的一部分。 C语法特别允许这样做。
答案 2 :(得分:2)
不要与字符串数组混淆:
{"xxx" ,
"yyyy",
"3534"}
您发布的是一个字符串。
答案 3 :(得分:2)
您的初始值设定项只包含一个字符串文字。看起来像多个“”封闭的字符串文字实际上会在翻译的第6个阶段(在预处理之后)合并为单个字符串文字。
答案 4 :(得分:2)
相邻的字符串文字是连接的,这有两种方法:宏组合字符串和可视化多行字符串文字,如上所述。比较一下代码的外观:
char const help_message[] = "Usage: %s [options] files ...\n\nOptions include:\n --verbose -v Be verbose\n --help -h Print this help message\n --output -o Specify output file\n\n";
想象一下试图维持这一点。此外,如果您使用多行字符串文字,则必须转义换行符或处理源代码使用的任何内容(可能不是'\n'
),并且您必须仔细查看缩进。所有这些都使您的示例中的代码更好。
以下是宏案例:
#define STRINGIZE_(v) #v
#define STRINGIZE(v) STRINGIZE_(v)
#define LOCATION __FILE__ ":" STRINGIZE(__LINE__)
#define MY_ASSERT(expr) do { \
if (!(expr)) \
some_function(LOCATION ": assertion failed in " \
__PRETTY_FUNCTION__ ": " #expr); \
} while (0)
(还有其他选择,例如传递单独的参数,并且使用GCC特定的__PRETTY_FUNCTION__
也是deprecated,但其余的都很方便,这是一个体面的“真实”例如,恕我直言。)
该代码中提到的其他问题需要注意:
#
是预处理器stringize运算符(##
是另一个特殊的预处理器运算符,用于标记粘贴)"filename.c:__LINE__"
打破if-else示例:
if (cond) MY_ASSERT(blah);
else other();
扩展为:
if (cond) do { ... } while(0);
else other();
而不是:
if (cond) if (...) ...;
else other();
这是不正确和令人惊讶的:
if (cond) {
if (...) {
...;
}
else {
other();
}
}