C/C++ 警告或禁止文字字符串连接

goz*_*zag 27 c c++ string warnings

有没有办法警告或禁止文字字符串连接,例如:

const char *a = "foo" " bar";
Run Code Online (Sandbox Code Playgroud)

我花了几个小时在一个大型静态数组中发现了一个错误

const char * a[] = {"foo" "bar"};
Run Code Online (Sandbox Code Playgroud)

代替

const char * a[] = {"foo", "bar"};
Run Code Online (Sandbox Code Playgroud)

cig*_*ien 50

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"};
                                 ^
                                ,
Run Code Online (Sandbox Code Playgroud)

这对于您展示的玩具示例并不完全适用,因为您需要有多个初始值设定项,并且只在几个地方缺少逗号,即:

// no warning
char const *b[]  = {"foo" "bar"};
// no warning
char const *c[]  = {"ok", "foo" "bar"};
// no warning
char const *d[]  = {"foo" "bar", "ok"};
Run Code Online (Sandbox Code Playgroud)

但是,当数组中有大量初始值设定项并且仅在几个地方出现拼写错误时,这似乎是理想的选择。

这是一个演示

GCC 似乎没有类似的警告,但有人要求添加它。

请注意,这仅适用于数组初始化。你的例子

const char *x = "foo" " bar";
Run Code Online (Sandbox Code Playgroud)

此警告(或我知道的任何其他警告)不会检测到。

另请注意,启用此警告可能会产生大量误报,但在尝试捕获错误时可以谨慎使用它。

  • GCC 通常会警告使用“-Wtraditional”(仅限 C)进行字符串连接,但可能不建议启用该选项。 (6认同)
  • 还找到了一个整洁的!https://clang.llvm.org/extra/clang-tidy/checks/bugprone/suspicious-missing-comma.html (4认同)

nie*_*sen 18

并不真地。字符串文字连接是 C/C++ 语法中不可或缺的一部分,并且有很多用例。因此,需要付出某种努力,但这可能会达不到发现错误的目标。

然而,字符串连接对于两个连续出现且中间只有空格的字符串文字非常严格,因此破坏空格将导致错误。例如,在这种情况下你可以写:

const *char[] = {("foo") ("bar")};  // Error
Run Code Online (Sandbox Code Playgroud)

这会导致错误,而预期的语句不会:

const *char[] = {("foo"), ("bar")};  // OK
Run Code Online (Sandbox Code Playgroud)

因此,简而言之,您无法通过某种方式显式地告诉编译器两个字符串文字可以连接并在所有其他情况下失败,因此您必须显式地告诉编译器何时不能连接字符串文字

  • _“...明确告诉编译器何时不能连接字符串文字...”_在它们之间放置 `,` 怎么样?我觉得我们已经绕了一圈了。 (12认同)
  • 我总是连接裸字符串文字,而不涉及任何宏,只是因为我喜欢换行代码。将每个单独的字符串/元素包装在括号中的建议解决方案很有趣。尽管编写和阅读 C 和 C++ 代码的经验相当丰富,但我无法立即知道该语法是否有效。这当然是有道理的,但我也觉得这很可疑。我倾向于在代码审查中标记这一点。虽然所提到的问题很有趣并且可能有一个解决方法,但正如理查德所建议的那样,它确实让我们回到了原点。 (6认同)
  • @RichardCritten是的,主要的一点是我认为OP正在寻找的解决方案在C/C++编译器服务中不存在。 (4认同)
  • @CodyGray:我发现括号最初令人惊讶,但没过多久我就思考了为什么它是有效的:字符串文字是“const char *”类型的对象(或者可能是C中的“char *”,我忘记)。括号可以出现在表达式中,并且计算结果为包装的子表达式。初始化列表需要一个“const char*”表达式的列表。我确实需要考虑几秒钟,但如果代码库到处都使用它,我就会习惯它。因此,更大的问题是,阅读代码时产生的额外语法噪音是否比可能出现的问题更糟糕。 (3认同)
  • 我认为大多数“必不可少”的用途都涉及将字符串文字与宏连接起来,例如 printf 格式字符串中使用的宏。真正需要连接字符串文字的情况很少见。 (2认同)
  • 括号是一个有趣的想法。一种保险,类似于“总是”在 if/then 分支或循环体周围使用大括号的规则,即使它们只是一行,以防止诸如 [Apple 的 SSL bug](https://www. codecentric.de/wissens-hub/blog/curly-braces)(即使该博客批评大括号修复肤浅且不够)。 (2认同)