例如,使用Xcode 11.3.1中的默认设置可以很好地编译以下代码:
#include <stdio.h>
int main(int argc, const char * argv[]) {
char* thing = "123";
thing[2] = '4';
printf("%s\n", thing);
return 0;
}
但是,在运行时,代码会用thing[2] = '4'
上的EXC_BAD_ACCESS捕获。我认为这是因为代表"123"
的字节的内存已编译为程序二进制文件中某个在现代处理器/ OS上标为code rather than data的位置。 (This answer确认—更不用说反汇编中有leaq 0x4d(%rip), %rsi ; "123"
行,将指针传递到相对于指令指针的地址!)
从自我修改代码的时代开始,C只是允许这种历史工件吗?我注意到,我也可以分配void* x = main;
,而不会抱怨我正在丢弃修饰符。
根据C99的基本原理,委员会中有些人希望字符串文字可以修改,因此该标准并未明确禁止这样做。
我可以对此进行进一步的讨论吗?实际上,是否有一种方法可以告诉clang和/或gcc 标记此类分配(即使实际上并未禁止使用它们)带有警告,而无需编译为C ++?
与C ++相反,在C字符串中,文字具有非恒定字符数组的类型。
但是根据C标准,任何尝试修改字符串文字都会导致未定义的行为。