为什么*(str + i)= *(str + j)在这里不起作用?

时间:2009-10-13 19:45:07

标签: c arrays string pointers reverse


void reverse(char *str){
    int i,j;
    char temp;
    for(i=0,j=strlen(str)-1; i<j; i++, j--){
     temp = *(str + i);
     *(str + i) = *(str + j);
     *(str + j) = temp;
     printf("%c",*(str + j));
    }
}



int main (int argc, char const *argv[])
{
    char *str = "Shiv";
    reverse(str);
    printf("%s",str);
    return 0;
}

当我使用char * str =“Shiv”时,我的反向函数的交换部分中的行,即str [i] = str [j]似乎不起作用,但是如果我将str声明为char str [] =“ Shiv“,交换部分有效吗?这是什么原因。我对这种行为感到有点困惑,当我试图运行该程序时,我不断收到“Bus error”消息。

8 个答案:

答案 0 :(得分:16)

当您使用char *str = "Shiv";时,您不拥有指向的内存,并且您不允许写入它。字符串的实际字节可以是程序代码中的常量。

当你使用char str[] = "Shiv";时,4(+ 1)个char字节和数组本身就在你的堆栈上,你可以随意给它们写信。

答案 1 :(得分:4)

char * str =“Shiv”获取一个指向字符串常量的指针,该字符串常量可以加载到只读的受保护的内存区域(例如可执行代码的一部分)。

答案 2 :(得分:4)

char *str = "Shiv";

这应该是:

const char *str = "Shiv";

现在你会有错误;)

答案 3 :(得分:1)

尝试

int main (int argc, char const *argv[])
{
    char *str = malloc(5*sizeof(char)); //4 chars + '\0'
    strcpy(str,"Shiv");
    reverse(str);
    printf("%s",str);
    free(str); //Not needed for such a small example, but to illustrate
    return 0;
}

代替。这将使您在使用指针时读/写内存。使用[]表示法直接在堆栈中分配空间,但使用const指针则不会。

答案 4 :(得分:1)

字符串文字是C和C ++中不可修改的对象。尝试修改字符串文字总是会导致未定义的行为。当您使用

获得“总线错误”时,这正是您所观察到的
char *str = "Shiv";

变体。在这种情况下,您的“反向”函数将尝试修改字符串文字。因此,行为未定义。

char str[] = "Shiv";

variant将在可修改的数组'str'中创建字符串文字的副本,然后'reverse'将对该副本进行操作。这样可以正常工作。

P.S。不要为字符串文字创建非const限定的指针。你的第一个变种应该是

const char *str = "Shiv";

(注意额外的'const')。

答案 5 :(得分:1)

字符串文字(您的“Shiv”)不可修改 您为指针指定了此类字符串文字的地址,然后尝试通过取消引用指针值来更改字符串文字的内容。这是一个很大的NO-NO。

将str声明为数组:

char str[] = "Shiv";

这将str创建为5个字符的数组,复制字符'S','h','i','v'和'\ 0'到str [0],str [1],...,str [4]。 str的每个元素中的值都是可修改的。

当我想使用指向字符串文字的指针时,我通常会将其声明为const。这样,当我的代码想要更改字符串文字的内容时,编译器可以通过发出消息来帮助我

const char *str = "Shiv";

想象一下,你可以对整数做同样的事情。

/* Just having fun, this is not C! */
int *ptr = &5;                      /* address of 5   */
*ptr = 42;                          /* change 5 to 42 */
printf("5 + 1 is %d\n", *(&5) + 1); /* 6? or 43?  :)  */

标准引用:

  

6.4.5字符串文字
  ...
      6 ...如果程序试图修改这样的数组[字符串文字],则行为是未定义的。

答案 6 :(得分:0)

char * str是指向一个字符块(字符串)的指针/引用。但它坐在一块内存中,所以你不能像那样分配它。

答案 7 :(得分:0)

有趣的是我从未注意到这一点。我能够在VS2008 C ++中复制这个条件。

通常,对常量进行就地修改是个坏主意。

无论如何,this post非常清楚地解释了这种情况。

  

第一个(char [])是您可以编辑的本地数据   (因为数组是本地数据)。

     

第二个(char *)是一个本地指针   全局,静态(常量)数据。您   不允许修改常量   数据

     

如果你有GNU C,你可以编译   用-fwritable-strings来保持   全局字符串   不变,但不建议这样做。