0
#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 上,他们给出了答案:

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

4

4 回答 4

3

你的分析是正确的。线

*x = x[n];

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


顺便说一句,我检查了你链接的网站。仅仅浏览了两分钟,我已经发现了多个不正确的代码示例(仅举几例, using gets, using char(not int) to assign return value ofgetchar等),所以我的建议是不要使用它。

于 2014-11-30T09:47:05.637 回答
3

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

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

于 2014-11-30T09:48:16.440 回答
0

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

const char *x ="Alice";

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

于 2015-12-15T05:44:20.883 回答
0

字符串文字的修改是未定义的行为。所以你观察到的行为,以及所描述的两种行为,都符合 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";
于 2015-12-15T10:00:31.147 回答