使用指针修改字符串

时间:2015-07-15 14:52:56

标签: c string

这两个代码必须更改字符<ul> <li> <a href='#'>Main</a> <ul> <li> <a href='#'>Submenu 1</a> </li> <li> <a href='#'>Submenu 2</a> </li> <li> <a href='#'>Submenu 3</a> </li> </ul> </li> </ul>

中的字符2
'4'

当我运行时,我在运行时会出现分段错误:

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

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

4 个答案:

答案 0 :(得分:6)

在第一种情况下,您通过尝试修改字符串文字来面对undefined behaviour。分段错误是UB常见的副作用之一。

在您的代码中,

 char *s = "hello";

基本上将字符串文字 "hello"的起始地址放入s。现在,您是否要修改*s(或*(s+n)的内容,前提是n不超出范围),它实际上会尝试修改字符串文字< / em>的。通常,字符串文字存储在只读存储器中,它们通常不允许被修改。引自C11,章节§6.4.5,字符串文字(强调我的)

  

如果这些数组的元素具有适当的值,则未指定这些数组是否相同。 如果程序试图修改此类数组,则行为未定义。

然而,在你的第二个案例中,你正在做

 char *s = argv[1];

argv[1]的值放入s。现在,s指向{em>字符串,并附有argv[1]。这里,argv[1](或argv[n]的内容不是只读的,可以修改。因此,使用*s(或*(s+n),提供的n不会超出范围),您可以修改内容。

此案例是已定义的行为,因为根据§5.1.2.2.2,程序启动

  

参数argcargv以及argv数组指向的字符串应由程序修改,并保留其最后存储的值在程序启动和程序终止之间。

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

答案 1 :(得分:4)

正如Sourav所说,尝试修改字符串文字会调用未定义的行为。如果您交替执行以下操作,则可以正常工作。

function clearOptions(select) {
    var selectParentNode = select.parentNode;
    if (selectParentNode) {
        var newSelect = select.cloneNode(false); // Make a shallow copy
        selectParentNode.replaceChild(newSelect, select);
        return newSelect;
    }
    return undefined;
}

function appendSelectHtml(data, target) {
    var selectHtml = [];
    $(data.items).each(function () {
        var selected = this.Selected ? ' selected' : '';
        var option = "<option value='" + this.Value + "'" + selected + ">" + this.Text + "</option>";
        selectHtml.push(option);
    });
    target = $(clearOptions(target[0])); //The item that was contained in the selector isn't in the DOM anymore
    target.append(selectHtml.join(""));       
}

答案 2 :(得分:3)

当你这样做时

char *s = "hello"; 

您指定*s指向字符串文字的开头,不可修改。这意味着您可以读取那里有什么但你无法改变它(这就是为什么

*(s+2)='4';

给你一个分段错误。

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

事实上,在您的第二种情况下,您使用的argv 具体解释为可在c标准中修改。

答案 3 :(得分:0)

字面值:'hello'在只读内存中,因此无法更改。

尝试更改它会导致seg错误事件

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

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

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

您可以在获取命令行参数的长度并为该长度执行malloc()后复制'strcpy()<1