#include<stdio.h>
int main(){
char *ptr="Helio";
ptr++;
printf("%s\n",ptr);
//*ptr++;
printf("%c\n",++*ptr);/*Segmentation fault on GCC*/
return 0;
}
Q1)这在Turbo C ++中运行良好,但在GCC上它会产生分段错误。我没有得到确切的理由。
可能是运营商优先权的原因之一。
Q2)每个编译器都有不同的运算符优先级吗?
我可以看到here ++的优先级高于解除引用运算符。可能是GCC和Turbo C ++对待它们的方式不同。
答案 0 :(得分:5)
不,运算符优先级由C标准定义,所有编译器都遵循相同的标准。
在这种情况下,Turbo C ++和GCC产生差异的原因是因为您修改了字符串文字,这是未定义的行为。
将其更改为:
char arr[] = "Helio";
char *ptr = arr;
您可以立即修改字符串的内容。请注意,arr
本身是数组名称,无法修改,因此我添加了一个新的指针变量ptr
并将其初始化为指向数组的第一个元素。
答案 1 :(得分:4)
在您的上一个printf()
行中,表达式++*ptr
相当于++ptr[0]
,而ptr[0] = ptr[0]+1
相当于ptr[0]=='H'
。自ptr[0]
起,您正尝试将'I'
的值更改为&ptr[0]
。
那是关键问题。由于"Helio"
指向常量H
的第一个元素,因此尝试更改第一个字符{{1}}会给您带来麻烦,因为它是未定义的行为。
答案 2 :(得分:2)
char* p = "some literal";
这是唯一合法的,因为C-people在标准的委员会谈判期间争吵的臭名昭着。您应该将其视为向后兼容性存在的奇怪现象。
这是您通过GCC收到的消息:
警告:已弃用从字符串常量转换为&#39; char *&#39;
请下次写下以下内容:
char const* p = "some literal";
让它成为你编码习惯的反射。那么你就无法编译你的错误行。
是:
++*ptr
在这里,您将获取常量字面值的第一个字符,并尝试将其递增到H
之后的字符,因此I
。但是这个内存区恰好位于写保护页面中,因为这是一个常量。标准非常不明确,你应该认为它是非法的。你的段错是来自这里。
我建议您下次在valgrind
运行您的程序,以获得更详细的错误消息。
在Yu Hao为你写的答案中,所发生的事情是所有的字符从存储文字的常量字符串池一个接一个地复制到堆栈分配的char数组,代码是编译器在初始化/声明站点写入,因此您可以取消引用其内容。