开发者

Why does *(str+i) = *(str +j) not work here?

开发者 https://www.devze.com 2022-12-08 05:06 出处:网络
void reverse(char *str){ int i,j; char temp; for(i=0,j=strlen(str)-1; i<j; i++, j--){ temp = *(str + i);

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开发者_Go百科. I was a bit puzzled by the behavior, I kept getting the message "Bus error" when I tried to run the program.


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.

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.


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

This should be :

const char *str = "Shiv";

And now you'll have an error ;)


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.


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

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.

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

const char *str = "Shiv";

(note the extra 'const').


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.

Declare str as an array instead:

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.

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 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.


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.


Interesting that I've never noticed this. I was able to replicate this condition in 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).

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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号