Gill Bates
Gill Bates

Reputation: 15217

Why assignment to a subscripted array works and assignment to a dereferenced pointer arithmetic expression - doesn't?

Kernighan & Ritchie 2nd ed. says:

The correspondence between indexing and pointer arithmetic is very close. By definition, the value of a variable or expression of type array is the address of element zero of the array. Thus after the assignment
pa = &a[0];

pa and a have identical values. Since the name of an array is a synonym for the location of the initial element, the assignment pa=&a[0] can also be written as
pa = a;

Rather more surprising, at least at first sight, is the fact that a reference to a[i] can also be written as *(a+i). In evaluating a[i], C converts it to a[i] immediately; the two forms are equivalent. Applying the operator & to both parts of this equivalence, it follows that and are also identical: a+i is the address of the i-th element beyond a. As the other side of this coin, if pa is a pointer, expressions may use it with a subscript; pa[i] is identical to *(pa+i). In short, an array-and-index expression is equivalent to one written as a pointer and offset.

And after reading this, I expect this two programs work identically:

/* Program 1 */
#include <stdio.h>


int main()
{
    char arr[] = "hello";
    arr[0] = 'H';
    printf("%s\n", arr);

}

/* Program 2 */
#include <stdio.h>


int main()
{
    char *arr = "hello";
    arr[0] = 'H';
    printf("%s\n", arr);

}

But only the first one is actually works. With the second one I get segmentation fault.

Why? Reference to an authoritative source would be much appreciated.

Upvotes: 1

Views: 83

Answers (4)

Gill Bates
Gill Bates

Reputation: 15217

K&R (5.5 Character Pointers and Functions):

There is an important difference between these definitions:

char amessage[] = "now is the time";   /* an array */
char *pmessage = "now is the time";    /* a pointer */

amessage is an array, just big enough to hold the sequence of characters and ′\0′ that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409422

When you define and initialize the array, all of the array is allocated in modifiable memory (usually the stack), and so you can modify the array any way you want.

When you use a string literal, the compiler will give you a pointer to a read-only zero-terminated array of char. Attempting to modify this array (which you do in the second example) leads to undefined behavior.

Upvotes: 3

haccks
haccks

Reputation: 106102

That's because the arr in first snippet is a char array and can be modified while in second snippet it is a string literal which is not subjected to change.

String literals might be stored in read only section of memory and modifying it will invoke undefined behavior.

Upvotes: 1

Yu Hao
Yu Hao

Reputation: 122493

It has nothing to do with pointer arithmetic. It's because in the second program:

char *arr = "hello";

arr points to a string literal, which can NOT be modified.

Upvotes: 2

Related Questions