字符串文本中的字符递增

Incrementing character in string literal

本文关键字:字符 文本 字符串      更新时间:2023-10-16
    #include<stdio.h>
    int main(){
       char *ptr="Helio";
       ptr++;
       printf("%sn",ptr);
       //*ptr++;
       printf("%cn",++*ptr);/*Segmentation fault on GCC*/
       return 0;
    }

问题 1(这在 Turbo C++ 中工作正常,但在 GCC 上它会产生分段错误。我不明白确切的原因。

可能是运算符优先级的原因之一。

问题 2(每个编译器是否具有不同的运算符优先级?

正如我在这里看到的,++ 的优先级高于取消引用运算符。可能是GCC和Turbo C++对待它们的方式不同。

不,运算符优先级由 C 标准定义,所有编译器都遵循相同的编译器。

在这种情况下,Turbo C++ 和 GCC 的结果差异的原因是您修改了字符串文本,这是未定义的行为。

将其更改为:

char arr[] = "Helio";
char *ptr = arr;

您现在可以修改字符串的内容。请注意,arr本身就是数组名称,无法修改,因此我添加了一个新的指针变量ptr并将其初始化为指向数组的第一个元素。

在最后printf()行中,表达式 ++*ptr 等效于 ++ptr[0] ,而 又等效于 ptr[0] = ptr[0]+1 。自 ptr[0]=='H' 以来,您正在尝试将 ptr[0] 的值更改为 'I'

这是那里的关键问题。由于&ptr[0]指向常数"Helio"的第一个元素,试图改变第一个字符H是有麻烦的,因为它是未定义的行为。

char* p = "some literal";

这之所以合法,只是因为C族人在标准的委员会谈判中争吵不休。您应该将其视为向后兼容的奇怪现象。

这是您通过 GCC 收到的消息:

警告:已弃用从字符串常量到"char*"的转换

下次请写以下内容:

char const* p = "some literal";

并让它成为你编码习惯的一种反射。那么你将无法编译你的错误行。

即:

++*ptr

在这里,您正在获取常量文字的第一个字符并尝试将其递增到H之后的内容,因此I 。但是这个内存区域恰好在写保护页中,因为这是一个常量。这是标准所定义的,您应该将其视为非法。你的段错误来自这里。我建议您下次运行程序valgrind以获取更详细的错误消息。

在余浩为你写的答案中,正在发生的事情是,所有字符都被编译器在初始化/声明站点编写的代码逐个复制到存储文本的常量字符串池,复制到堆栈分配的 char 数组,因此你可以取消引用它的内容。