4

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",交换部分有效吗?这是什么原因。我对这种行为有点困惑,当我尝试运行程序时,我不断收到“总线错误”的消息。

4

8 回答 8

16

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

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

于 2009-10-13T19:47:48.633 回答
4

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

于 2009-10-13T19:48:28.487 回答
4
char *str = "Shiv";

这应该是:

const char *str = "Shiv";

现在你会有一个错误;)

于 2009-10-13T19:49:53.683 回答
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 指针不会。

于 2009-10-13T19:50:26.053 回答
1

字符串文字在 C 和 C++ 中都是不可修改的对象。尝试修改字符串文字总是会导致未定义的行为。这正是您在收到“总线错误”时所观察到的

char *str = "Shiv";

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

char str[] = "Shiv";

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

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

const char *str = "Shiv";

(注意额外的'const')。

于 2009-10-13T19:51:43.633 回答
1

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

将 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 ... 如果程序尝试修改这样的数组[字符串文字],则行为未定义。

于 2009-10-13T19:55:47.067 回答
0

char *str 是对字符块(字符串)的指针/引用。但是它位于内存块中的某个位置,因此您不能像那样分配它。

于 2009-10-13T19:49:26.770 回答
0

有趣的是我从来没有注意到这一点。我能够在 VS2008 C++ 中复制这种情况。

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

无论如何,这篇文章非常清楚地解释了这种情况。

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

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

如果您有 GNU C,您可以使用 -fwritable-strings 进行编译,以防止全局字符串保持不变,但不建议这样做。

于 2009-10-13T19:53:11.440 回答