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)它开始格式化硬盘(但不确定可能性有多大)。;-)