当我们尝试修改字符串常量时会发生什么?

时间:2014-11-30 09:37:37

标签: c linux pointers string-constant

#include<stdio.h>
#include<string.h>

int main()
{
    int i, n;
    char *x="Alice"; // ....... 1
    n = strlen(x);   // ....... 2
    *x = x[n];       // ....... 3
    for(i=0; i<=n; i++)
    {
        printf("%s ", x);
        x++;
    }
    printf("\n");
    return 0;
}

无法修改字符串常量。在上面的代码中* x表示'A'。在第3行中,我们尝试修改字符串常量。写这个陈述是否正确?当我在 Linux 上运行此代码时,我得到分段错误。但是在www.indiabix.com上,他们给出了答案:

  

如果你在Windows平台上用Turbo C编译和执行这个程序,它会给出 lice ice ce e 它可能在其他平台上提供不同的输出(取决于编译器和机器)。本网站提供的在线C编译器将输出 Alice lice ice ce e (它在Linux平台上运行)。

4 个答案:

答案 0 :(得分:3)

您的分析是正确的。这条线

*x = x[n];

正在尝试修改字符串文字,因此它是未定义的行为。


顺便说一下,我检查了你链接的网站。只浏览它两分钟,我已经找到了多个不正确的代码示例(仅举几例,使用gets,使用char(不是int)来指定返回值{{ 1}}等等,所以我的建议是不要使用它。

答案 1 :(得分:3)

您的分析是正确的,但与您引用的内容并不矛盾。

代码被破坏了。答案已经确认它在不同的实现上可能表现不同,并且通过两种不同的实现给出了两种不同的输出。您碰巧找到了以第三种方式运行的实现。那很好。

答案 2 :(得分:0)

在此代码中,"Alice"的内存将位于可执行文件的只读数据部分,而 x是指向该只读位置的指针。当我们尝试修改只读数据部分时,它不应该允许。但char *x="Alice";告诉编译器 x 被声明为指向character.ie的指针, x 指向可以修改的字符(不读取 - 只要)。所以编译器会认为它可以被修改。因此,行*x = x[n];在不同的编译器上的行为会有所不同。所以它将是未定义的行为 正确的声明方式来分配字符串文字,如下所示

 const char *x ="Alice";

然后只能预测编译器行为。

答案 3 :(得分:0)

字符串文字的修改是未定义的行为。因此,您观察到的行为以及所描述的两种行为符合C标准的要求(通过向您的老板和您的配偶发送电子邮件,或让恶魔飞出您的鼻子)。这三个实际上都是非常合理的动作(修改'常量',忽略写入或发出错误信号)。

使用GCC,当您将字符串文字的地址分配给指向(可写)字符的指针时,可以要求发出警告:

cc -g -Wall -Wextra -Wwrite-strings   -c -o 27211884.o 27211884.c
27211884.c: In function ‘main’:
27211884.c:7:13: warning: initialization discards ‘const’ qualifier from pointer target type [enabled by default]
     char *x="Alice"; // ....... 1
             ^

默认情况下,此警告在编译C ++时处于启用状态,但不适用于C,因为char*通常用于旧代码库中的字符串文字。我建议在编写新代码时使用它。

有两种正确的方法来编写示例代码,具体取决于您是否希望字符串实际上是常量:

const char *x = "Alice";
char x[] = "Alice";