C 为什么我可以通过传递变量而不是传递真正的字符串来反转字符串?(简单代码)

C 为什么我可以通过传递变量而不是传递真正的字符串来反转字符串?(简单代码),c,string,function,reversing,C,String,Function,Reversing,下面是显示字符串“dcba”的方法: 我如何获得“分段错误”(为什么?): 下面是反转字符串的函数: char *strrev(char *s) { int i, j; char aux; for(i=0, j=strlen(s)-1; i<j; i++, j--) { aux = s[j]; s[j] = s[i]; s[i] = aux; } return s; } char*stre

下面是显示字符串“dcba”的方法:

我如何获得“分段错误”(为什么?):

下面是反转字符串的函数:

char *strrev(char *s)
{
    int i, j;
    char aux;

    for(i=0, j=strlen(s)-1; i<j; i++, j--)
    {
        aux = s[j];
        s[j] = s[i];
        s[i] = aux;
    }

    return s;
}
char*strev(char*s)
{
int i,j;
char aux;

对于C中的(i=0,j=strlen(s)-1;i,这是因为试图修改字符串文字是被视为未定义行为的事情之一

文字字符串修改在原始C标准中被标记为未定义行为的原因(请记住,ANSI/ISO C标准机构的原始意图是编纂现有实践,而不是发明新的语言)是因为当时存在的一些实现将字符串文本存储在只读内存中,或者共享相同的字符串文本以减少内存使用

而且,由于该标准的每一次迭代都是在该点值向后兼容性之后进行的(有些实现可能仍然会优化空间或保护字符串文字免受无意中的损坏),因此人们并不真正希望对其进行更改


总之,未定义的行为通常是不好的,不要这样做。

在C中,这是因为试图修改字符串文字是被视为未定义行为的事情之一

文字字符串修改在原始C标准中被标记为未定义行为的原因(请记住,ANSI/ISO C标准机构的原始意图是编纂现有实践,而不是发明新的语言)是因为当时存在的一些实现将字符串文本存储在只读内存中,或者共享相同的字符串文本以减少内存使用

而且,由于该标准的每一次迭代都是在该点值向后兼容性之后进行的(有些实现可能仍然会优化空间或保护字符串文字免受无意中的损坏),因此人们并不真正希望对其进行更改


总之,未定义的行为通常是不好的,不要这样做。

字符串文字是常量。小心,@overtheboard。虽然您明智地将文字视为常量,但该词在标准中有特定的含义。它们不必是不可更改的,事实上,第6阶段创建了一个
字符数组,而不是
const char
。我肯定你指的是前者,但我今天觉得不太学究:-)这段代码对我来说很有用。@Twinkle,有时,未定义的行为会起作用(在某些实现中,在某些情况下,当使用某些标志编译并在任何一天运行时,而不是在蓝月之后的某一天)。这是它最隐秘的属性:-)字符串文字是常量。小心,@overtheboard。虽然您明智地将文字视为常量,但该单词在标准中有特定的含义。它们不必是不变的,事实上,第6阶段创建了一个
字符数组,而不是
常量字符你的意思是前者,但我今天觉得不明智的迂腐:-)这段代码对我来说很有用。@Twinkle,有时,未定义的行为是有效的(在某些实现中,在某些情况下,当使用某些标志编译并在任何一天运行时,而不是在蓝月之后的某一天)。这是它最阴险的特性:-)好吧,不仅仅是预标准。这些天仍然是这样做的。@Rudy,抱歉,我不是想说今天不是这样做的,只是因为在C89/90之前是这样做的,所以他们必须尊重它。我会尝试更改答案来澄清。不需要道歉。但文字通常是只读内存中有问题。因此segfault.AFAIK,而不仅仅是预标准。这些天仍然是这样做的。@Rudy,抱歉,我不是想说今天不是这样做的,只是因为在C89/90之前是这样做的,所以他们不得不尊重它。我会尝试更改答案以澄清。不需要道歉。但文字通常是这样的仍在只读存储器中。因此存在SEG故障。
puts(strrev("abcd"));
char *strrev(char *s)
{
    int i, j;
    char aux;

    for(i=0, j=strlen(s)-1; i<j; i++, j--)
    {
        aux = s[j];
        s[j] = s[i];
        s[i] = aux;
    }

    return s;
}