C 字符串和操纵字符串,这里到底发生了什么。?

C 字符串和操纵字符串,这里到底发生了什么。?,c,string,C,String,为什么我在运行这个程序时会出现“分段错误(内核转储)”的错误,它有什么问题 #include <stdio.h> int main() { char *p = "Sanfoundry C-Test"; p[0] = 'a'; p[1] = 'b'; printf("%s", p); return 0; } #包括 int main(){ char*p=“Sanfoundry C-Test”; p[0]=“a”; p[1]=‘b’;

为什么我在运行这个程序时会出现“分段错误(内核转储)”的错误,它有什么问题

#include <stdio.h>

int main() {

    char *p = "Sanfoundry C-Test";

    p[0] = 'a';

    p[1] = 'b';

    printf("%s", p);

    return 0;
}
#包括
int main(){
char*p=“Sanfoundry C-Test”;
p[0]=“a”;
p[1]=‘b’;
printf(“%s”,p);
返回0;
}

字符串文字在C中不可修改:

char *p = "Sanfoundry C-Test";
p[0] = 'a';
最后一条语句调用未定义的行为

使用用字符串文字初始化的字符数组来定义行为:

char p[] = "Sanfoundry C-Test";
p[0] = 'a';

这是字符数组和字符指针之间的区别

char p[]="Sanfoundry C-Test";
那你就可以了

p[0]='a';
p[1]='b';
但是如果p是一个指针,你就不能这样做

有关更多信息,请参阅下面提供的链接


正如其他人所说,这不应该这样做,因为您正在修改一些本应(通常是)不可修改的内容

char *p = "Sanfoundry C-Test";
这声明了一个指针,并将其指向(将指针中包含的地址设置为开头)文本(该文本是常量,不应修改,并且可能无法修改而不会出错)
“SANFORY C-Test”

但是,好了,您正在询问代码的其余部分是什么意思,所以让我们首先纠正这个问题:

char p[] = "Sanfoundry C-Test";
声明具有给定内容的
字符数组(字符
'S'
'a'
'n'
等,后跟0字符)。现在,C将这样的数组视为文本字符串

p[0] = 'a';
更改该数组的第一个字符(数组“开始计数”为0),因此字符串中的
'S'
更改为
'a'

p[1] = 'b';

这会将第二个字符更改为
'b'
。现在字符串是
“abnc-Test”
。最后的
printf()
然后在控制台中显示该值。

它的行为未定义。通过适当的优化,我敢打赌它会打印“Sanfoundry C-Test”。这一点你都不能指望。还值得注意的是,这是C++11中的一个编译器错误。启用所有警告,并大声读出它们/然后您将看到这是怎么回事/文字是常量,以及失败的原因/这就是为什么您最终会出现未定义的行为:
“不推荐将字符串常量转换为‘char*””
。在带有编译器的Mac电脑上
Apple LLVM 5.1版(clang-503.0.40)
会出现
总线错误
。如果处理字符串文本,最好(至少)总是使用指向
const char
的指针:
const char*p=“San…”p
衰减为指针,以便索引工作。这里的区别是数组复制了字符串,这样你就可以修改内存了。这并不是数组和指针之间的区别。OP完全可以做
char*p=(char[]){“Sanf…”并且仍然在处理指针。另一方面,使用
const char
s数组并对其进行写入(在施放
const
之后)将非常困难。因此,请原谅我缺乏C语言知识,但是
(char[]{“…”}
不会创建一个立即销毁的临时
char[]
,使
p
处于悬空状态?创建对象的生存期将是封闭块的生存期。是的,这与字符串文字不同,但是您的建议(
charp[]=“…”
)具有完全相同的生存期。但那不是我的重点。OP的问题实际上与指针/数组的差异无关;仅仅因为您提供了一个涉及数组的解决方案,并不意味着它是一个数组/指针问题。这仅仅是关于字符串文字不可修改的问题。四种最有可能的
未定义行为是(没有特定顺序):1)编译器警告,2)SEGFAULT/Bus错误,3)字符串未修改,4)它似乎按预期工作,字符串被修改(真的是最糟糕的结果).5)它开始格式化硬盘(但不确定可能性有多大)。;-)