#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平台上运行)。
答案 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";