有没有一种方法可以警告或禁止字面字符串连接,例如:
const char *a = "foo" " bar";
我花了数小时的时间在一个巨大的静态数组中寻找错误。
const char * a[] = {"foo" "bar"};
替代
const char * a[] = {"foo", "bar"};
Clang有一个警告-Wstring-concatenation,专门设计用来捕捉这种错误:
warning: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Wstring-concatenation]
char const *a[] = { "ok", "foo" "bar", "ok"};
^
,
这个例子不会完全适用于你展示的玩具例子,因为你需要有几个初始化器,而只有在一些地方缺少逗号,例如:
// no warning
char const *b[] = {"foo" "bar"};
// no warning
char const *c[] = {"ok", "foo" "bar"};
// no warning
char const *d[] = {"foo" "bar", "ok"};
但是当您在数组中有大量的初始化程序,并且只在其中几个位置上犯了一个打字错误时,这似乎是理想的。
这里是一个演示。
GCC似乎没有相应的警告,但已经有一个请求要求添加它。
请注意,这仅适用于数组初始化。您的例子为
const char *x = "foo" " bar";
不会被此警告(或我所知的任何其他警告)检测到。
还要注意,启用此警告可能会产生很多误报,但在尝试捕捉错误时可以适度使用它。
-Wtraditional
(仅限C语言)时警告字符串连接,但启用该选项可能不可取。 - nielsen不完全是这样。字符串字面值的连接是 C/C++ 语法中不可或缺的一部分,有许多用例。因此需要一定的努力,这可能会破坏捕捉错误的目标。
然而,字符串连接非常严格地作用于两个字符串字面值,在它们之间只有空格时才能正常工作,因此打破空格将导致错误。例如,在这种情况下,您可以这样编写:
const *char[] = {("foo") ("bar")}; // Error
这会导致错误,而预期的语句则不会:
const *char[] = {("foo"), ("bar")}; // OK
,
怎么样?我感觉我们已经走了一圈。 - Richard Crittenconst char*
类型的对象(在 C 中可能是 char*
,我忘记了)。 括号可以出现在表达式中,并计算封装的子表达式。初始化器列表需要一系列 const char*
表达式。我确实需要思考几秒钟,但是如果代码库各处都使用这种写法,我会习惯的。因此,更大的问题是阅读代码时是否应该为此额外的语法噪音而感到不适,是否比可能出现的问题更糟糕。 - Peter Cordes以下任何一个宏都可以防止意外连接两个字符串。
C++(C预处理器)宏通常非常棒。在元素列表的末尾添加逗号也是合法的。
你可以像这样做:
#define STRINGCOMMA(a) a,
const char *x[] = {
STRINGCOMMA("foo")
STRINGCOMMA("bar")
};
甚至可以这样:
#define QUOTESTRINGCOMMA(a) #a,
const char *x[] = {
QUOTESTRINGCOMMA(foo)
QUOTESTRINGCOMMA(bar)};
逗号已经为您添加了,如果您不小心自己添加逗号将是非法的。
如果您感兴趣,还可以进一步将此概念扩展,以允许创建具有相同参数但不同处理的并行列表:
#define VARLIST \
DO(foo) \
DO(bar)
#define DO(a) #a,
const char *x[] = {
VARLIST
};
#undef DO
如果您想从相同的名称列表中创建枚举列表和字符串列表,那么这将非常有用。
嗯,你可以这样做:
char const * a [] =
{ "foo"
, "bar"
, "baz"
, "asdf"
, "ghjk"
};
"
结尾的行,可能会有尾随空格。如果需要,这些可以通过grep '"\s*$'
捕捉到。 - Tom Karzesstring3
后忘记了,
")和为什么要允许字符串字面值的连接?(2010年。"最近我被一个微妙的bug所困扰......我忘记了two
后面的,
"*) - Peter Mortensen