编译时错误与运行时错误

时间:2013-03-11 08:03:40

标签: c++ c

我很困惑为什么编译器会给出

const char s[]="hello";
s[2]='t';                 // Compile Time Error

char *t = "hello";
*(t+2)='u';              // Run time Error

我猜两种情况下编译器都应该给出编译时错误。任何人都可以告诉我这种方式的特殊原因吗?

4 个答案:

答案 0 :(得分:6)

在第一种情况下,您正在写一个const并且编译器注意到并且可以拒绝它。

在第二种情况下,t是指向非const char的指针,因此您可以取消引用它并在*(t+2)处写入。但是,由于t使用指向只读段的指针进行初始化,因此您在运行时会遇到分段违规。

您可能会痛苦地配置链接器以将所有数据放入可写段中。这是丑陋的,非标准的。

P.S。一些复杂的静态分析器(可能Frama-C)可能会在不运行程序的情况下捕获这两个错误。也可以想象扩展GCC,例如使用MELT添加此类检查(但这是非常重要的工作,可能很难获得资助)。

答案 1 :(得分:6)

向后兼容性。

您无法修改const char。这很明显。

不显而易见的是,字符串文字的类型实际上是指向常量字符的指针,而不是指向字符的指针。因此,第二个声明实际上是错误的类型。但是,由于历史原因,这得到了支持。


请注意,上述内容有点谎言。字符串文字实际上是char[]类型而不是指针。

特别是,字符串文字的类型是char[]而不是C89和C99中的const char[] [我认为C11,但不确定]。那时实际上不是错误,但是数据存储在只读段中,所以尝试写入它是未定义的行为。


另外,对于它的价值,你可以使用-Wwrite-strings和gcc(g ++已经包含它)来警告这一点。


更多信息herehere

答案 2 :(得分:3)

执行:char *t = "hello";时, t 是指向代码部分中的内存的指针,因此您无法更改它。因为它是只读,所以在运行时会出现分段错误。

当你这样做时:const char s[]="hello";然后 s 是一个在堆栈上的字符数组,但它是const,所以你可以不要改变它并且你得到一个编译错误(编译器知道它是 const 所以他不允许你改变它。)

当您不希望更改String时使用const是好的,因为这会产生编译错误,这比运行时错误更好。

答案 3 :(得分:2)

考虑以下一系列陈述:

char *t = "hello";
char s[5];
t = s;
*(t+2)='u';

这一系列语句不会产生运行时错误,因为语句*(t+2)='u';无效。它试图在您的情况下修改const(只读)内存位置,但编译器无法知道是否会发生访问冲突。