【问题标题】:What should happen, when we try to modify a string constant?当我们尝试修改字符串常量时会发生什么?
【发布时间】:2014-11-30 09:37:36
【问题描述】:
#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 上运行此代码时,我遇到了 segmentation fault。但在 www.indiabix.com 上,他们给出了答案:

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

【问题讨论】:

  • 那是什么书?他们真的像你一样修改吗?因为您从书中发布的答案表明他们只是在移动指针并打印它。而且无论书上说什么,都不允许修改字符串文字,这样做会导致未定义的行为
  • @BlueMoon 答案表明他们确实将*x 设置为'\0' (x[n] == '\0'):没有它,编译器就无法将“lice ice ce e”作为输出。跨度>
  • 如果您认为下面的任何帖子回答了您的问题,请点击旁边的检查符号接受它。这将使答案浮到顶部,并为您和回答者奖励一些声望点。

标签: c linux pointers string-constant


【解决方案1】:

您的分析是正确的。线

*x = x[n];

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


顺便说一句,我检查了您链接的网站。仅仅浏览了两分钟,我已经发现了多个不正确的代码示例(仅举几例,使用gets,使用char(不是int)分配getchar的返回值等),所以我的建议是不要使用它。

【讨论】:

  • 你能给我任何网站链接或任何书籍来练习 C 上的问题吗?我正在那个网站练习,因为我没有任何其他选择。 @余浩
  • @JhansiRani, 试着读几本书.. The C programming LanguageLet us C 是我的选择..
【解决方案2】:

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

代码已损坏。答案已经承认它在不同的实现上可能表现不同,并通过两个不同的实现给出了两个不同的输出。您碰巧找到了以第三种方式运行的实现。没关系。

【讨论】:

    【解决方案3】:

    字符串文字的修改是未定义的行为。所以你观察到的行为,以及所描述的两种行为,都符合 C 标准的要求(就像给你的老板和你的配偶发电子邮件一样,或者让恶魔从你的鼻子里飞出来)。这三个实际上都是相当合理的操作(修改“常量”、忽略写入或发出错误信号)。

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

    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";
    

    【讨论】:

      【解决方案4】:

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

      const char *x ="Alice";
      

      只有这样才能预测编译器的行为。

      【讨论】:

        猜你喜欢
        • 2011-10-20
        • 1970-01-01
        • 2018-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-02
        • 1970-01-01
        • 2014-08-02
        相关资源
        最近更新 更多