用指针修改一个string

这两个代码必须改变字符'4'的字符2

 int main(int argc, char *argv[]){ char *s = "hello"; *(s+2)='4'; printf( "%s\n",s); return 0; } 

当我运行这个时,我得到分段错误,而当我运行这个:

 int main(int argc, char *argv[]){ char *s = argv[1]; *(s+2)='4'; printf( "%s\n",s); return 0; } 

我知道还有其他方法可以做到这一点。 这两个程序有什么区别?

在你的第一种情况下,你正试图修改一个string文字来面对未定义的行为 。 分段故障是UB常见的副作用之一。

在你的代码中,

  char *s = "hello"; 

基本上把string文字 "hello"的起始地址放在s 。 现在,你想修改*s (或*(s+n) ,如果n不超出范围),它实际上会试图修改该string 。 通常,string文本存储在只读存储器中, 通常不允许修改。 引用C11 ,第6.4.5节, string (强调我的)

没有说明这些数组是否是不同的,只要它们的元素具有适当的值。 如果程序试图修改这样一个数组,行为是不确定的。

但是,在第二种情况下,你在做

  char *s = argv[1]; 

argv[1]的值argv[1] s 。 现在, s指向由argv[1]包含的string 。 这里, argv[1] (或者argv[n] )的内容不是只读的,可以修改。 所以,使用*s (或*(s+n) ,如果n不超出范围),您可以修改内容。

这种情况是定义的行为 ,因为按照§5.1.2.2.2, 程序启动

参数argcargv以及argv数组所指向的string应该可以被程序修改 ,并在程序启动和程序终止之间保留它们的最后存储的值。

所以,第二种情况是使用argv[n]一种特殊情况,它是由C标准规则可修改的。

正如Sourav所说,尝试修改string文字会调用未定义的行为。 如果你交替做了以下,它会正常工作。

 int main(int argc, char *argv[]){ char s[] = "hello"; *(s+2)='4'; printf( "%s\n",s); return 0; } 

当你这样做

 char *s = "hello"; 

您将*s指定为不可修改string文本的开头。 这意味着你可以阅读那里有什么,但你不能改变它(这是为什么

 *(s+2)='4'; 

给你一个分段错误。

在你的第二种情况下,你没有给你的指针一个string文字,所以你可以修改它。

事实上,在你的第二种情况下,你正在使用argv ,这个特殊的解释是在c标准中可以修改的。

字面意思:'你好'是只读内存,所以不能改变。

试图改变它导致seg故障事件

尝试从argv []更改string数组有同样的问题。 值是只读的

尝试更改命令行参数会导致seg故障事件。

你可以使用:'char s [] =“hello”; “因为这将把文字放在堆栈上,在那里可以改变。

你可以在获得命令行参数的长度后复制“strcpy()”,并执行该长度的malloc()+ 1