随着不同语言之间不断的来回切换,我时不时地发现自己尝试用 C/C++ 编写 Python 或 JS 语法片段。
不止一次让我困惑的是尝试使用
+
运算符将数字附加到字符串文字:
foo(const char*);
foo("the number is " + 6);
很高兴编译将指向字符串
char*
的 "mber is "
指针传递到我的函数中。如果我写的话会更有趣:
foo("the number is " + 20);
有人知道可以捕获此问题的警告选项吗?
GCC 确实通过
-Warray-bounds
中包含的 -Wall
警告发出关于出界指针算术的警告。然而,需要启用优化才能使其发挥作用,例如使用选项 -Wall -O2
GCC 13 产生:
<source>:4:45: warning: array subscript 20 is outside array bounds of 'const char [15]' [-Warray-bounds=]
4 | some_function_that_takes_a_const_chr_ptr("the number is " + 20);
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
对于界内情况,Clang 有一个
-Wstring-plus-int
警告,但 GCC 目前没有等效的警告。
实现等效的补丁已于 2017 年提交,但似乎从未进一步进展。
由于宏替换不会替换在其自身替换中找到的宏,因此您可以在函数调用中插入宏。考虑这个宏:
#define foo(argument) foo(*&(argument))
如果
argument
是字符串文字的数组,我们可以用 &
获取它的地址,然后用 *
解引用生成数组,之后发生通常的数组到指针的转换,函数foo
被调用。
如果
argument
是字符串文字加整数,则数组到指针的转换发生在 &
应用之前,因此 &
的操作数是右值,而不是左值,编译器会抱怨。
因此我们有:
#include <stdio.h>
void foo(const char *x)
{
printf("I am happy.\n");
}
#define foo(argument) foo(*&(argument))
int main(void)
{
foo("the number is "); // This will compile without complaint.
foo("the number is " + 6); // This will get an error.
}