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

时间:2022-04-29 13:25:26

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;
}

When I use char *str = "Shiv" the lines in the swapping part of my reverse function i.e str[i]=str[j] dont seem to work, however if I declare str as char str[] = "Shiv", the swapping part works? What is the reason for this. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.

当我使用char *str = "Shiv"时,我的反向函数的交换部分中的行。e str[i]=str[j]似乎不工作,但如果我将str声明为char str[] = "Shiv",交换部分是否工作?原因是什么?我对这种行为有点迷惑,当我试图运行程序时,我不断地收到“总线错误”的消息。

8 个解决方案

#1


16  

When you use char *str = "Shiv";, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.

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

When you use char str[] = "Shiv";, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.

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

#2


4  

The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.

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

#3


4  

char *str = "Shiv";

This should be :

这应该是:

const char *str = "Shiv";

And now you'll have an error ;)

现在你会有一个错误;

#4


1  

Try

试一试

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;
}

instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.

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

#5


1  

String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with

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

char *str = "Shiv";

variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.

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

The

char str[] = "Shiv";

variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.

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

P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been

注意,不要为字符串文字创建非conconst限定的指针。您的第一个变体应该是

const char *str = "Shiv";

(note the extra 'const').

(注意额外的“常量”)。

#6


1  

String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.

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

Declare str as an array instead:

将str作为一个数组声明:

char str[] = "Shiv";

This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str are modifiable.

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

When I want to use a pointer to a string literal, I usually declare it const. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal

当我想要使用一个指向字符串文字的指针时,我通常会声明它是const。这样,当我的代码想要更改字符串文本的内容时,编译器就可以帮助我发出一条消息。

const char *str = "Shiv";

Imagine you could do the same with integers.

假设你可以对整数做同样的事情。

/* 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?  :)  */

Quote from the Standard:

引用标准:

6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.

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

#7


0  

char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.

char *str是指向字符块(字符串)的指针/引用。但是它位于内存块的某个地方所以你不能像这样分配它。

#8


0  

Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.

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

Typically, it is a bad idea to do in-place modification of constants.

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

In any case, this post explains this situation pretty clearly.

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

The first (char[]) is local data you can edit (since the array is local data).

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

The second (char *) is a local pointer to global, static (constant) data. You are not allowed to modify constant data.

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

If you have GNU C, you can compile with -fwritable-strings to keep the global string from being made constant, but this is not recommended.

如果您有GNU C,您可以使用-fwritable-strings进行编译,以避免使全局字符串成为常量,但不建议这样做。

#1


16  

When you use char *str = "Shiv";, you don't own the memory pointed to, and you're not allowed to write to it. The actual bytes for the string could be a constant inside the program's code.

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

When you use char str[] = "Shiv";, the 4(+1) char bytes and the array itself are on your stack, and you're allowed to write to them as much as you please.

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

#2


4  

The char *str = "Shiv" gets a pointer to a string constant, which may be loaded into a protected area of memory (e.g. part of the executable code) that is read only.

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

#3


4  

char *str = "Shiv";

This should be :

这应该是:

const char *str = "Shiv";

And now you'll have an error ;)

现在你会有一个错误;

#4


1  

Try

试一试

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;
}

instead. That will get you read/write memory when using pointers. Using [] notation allocates space in the stack directly, but using const pointers doesn't.

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

#5


1  

String literals are non-modifiable objects in both C and C++. An attempt to modify a string literal always results in undefined behavior. This is exactly what you observe when you get your "Bus error" with

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

char *str = "Shiv";

variant. In this case your 'reverse' function will make an attempt to modify a string literal. Thus, the behavior is undefined.

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

The

char str[] = "Shiv";

variant will create a copy of the string literal in a modifiable array 'str', and then 'reverse' will operate on that copy. This will work fine.

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

P.S. Don't create non-const-qualified pointers to string literals. You first variant should have been

注意,不要为字符串文字创建非conconst限定的指针。您的第一个变体应该是

const char *str = "Shiv";

(note the extra 'const').

(注意额外的“常量”)。

#6


1  

String literals (your "Shiv") are not modifiable.
You assign to a pointer the address of such a string literal, then you try to change the contents of the string literal by dereferencing the pointer value. That's a big NO-NO.

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

Declare str as an array instead:

将str作为一个数组声明:

char str[] = "Shiv";

This creates str as an array of 5 characters and copies the characters 'S', 'h', 'i', 'v' and '\0' to str[0], str[1], ..., str[4]. The values in each element of str are modifiable.

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

When I want to use a pointer to a string literal, I usually declare it const. That way, the compiler can help me by issuing a message when my code wants to change the contents of a string literal

当我想要使用一个指向字符串文字的指针时,我通常会声明它是const。这样,当我的代码想要更改字符串文本的内容时,编译器就可以帮助我发出一条消息。

const char *str = "Shiv";

Imagine you could do the same with integers.

假设你可以对整数做同样的事情。

/* 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?  :)  */

Quote from the Standard:

引用标准:

6.4.5 String literals
...
6 ... If the program attempts to modify such an array [a string literal], the behavior is undefined.

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

#7


0  

char *str is a pointer / reference to a block of characters (the string). But its sitting somewhere in a block of memory so you cannot just assign it like that.

char *str是指向字符块(字符串)的指针/引用。但是它位于内存块的某个地方所以你不能像这样分配它。

#8


0  

Interesting that I've never noticed this. I was able to replicate this condition in VS2008 C++.

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

Typically, it is a bad idea to do in-place modification of constants.

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

In any case, this post explains this situation pretty clearly.

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

The first (char[]) is local data you can edit (since the array is local data).

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

The second (char *) is a local pointer to global, static (constant) data. You are not allowed to modify constant data.

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

If you have GNU C, you can compile with -fwritable-strings to keep the global string from being made constant, but this is not recommended.

如果您有GNU C,您可以使用-fwritable-strings进行编译,以避免使全局字符串成为常量,但不建议这样做。