Reputation: 1570
I have the following code:
typedef struct{
char *name;
int age;
} person;
int main(){
person Peter = {"peter", 19};
person Petercp = Peter;
Peter.name[0] = 'a';
Petercp.name = "hello";
printf("%s %d\n", Peter.name, Peter.age);
printf("%s %d\n", Petercp.name, Petercp.age);
}
the compiler gives me the error message of "BAD ACCESS" for the line
Peter.name[0] = 'a'
but the following line seems good
Petercp.name = "hello";
It seems as if the array of person.name is a pointer to constant. Am I right to make the conclusion?
And, if I declare the array inside the struct to be
char name[];
I am again allowed to make the change for
Peter.name[0] = 'a'
Why is that?
Upvotes: 0
Views: 145
Reputation: 229108
When you do person Peter = {"peter", 19};
, you point name
to a string literal "peter".
Peter.name[0] = 'a'
tries to change the 1. element in what name
is pointing to. Modifying a string literal is undefined behavior and in your case it causes a crash. In practice string literals are often loaded in a read only section of memory.
On the other hand doing Petercp.name = "hello";
just changes the pointer to point somewhere else, which is fine.
If you declare the name member as char name[64]
then the initializer
person Peter = {"peter", 19};
will copy the string "peter" into the name
array. The name array is just an ordinary char array where you can change the individual elements.
Upvotes: 4
Reputation: 7823
Because you haven't declared any space for peter, so Peter.name[0] doesn't exist.
When you do the initial assignment using a constant string the compiler is assigning the constant string value to that, and you can't change constants.
The following would work:
int main(){
person Peter;
Peter.age = 19;
Peter.name = calloc(sizeof(*(Peter.name)),sizeof("hello")+1);
strncpy(Peter.name,"hello",sizeof("hello"));
Peter.name[0] = 'a';
printf("%s %d\n", Peter.name, Peter.age);
free(Peter.name);
}
The difference here is that a straight Peter.name = "hello"
make Peter.name
point directly to the (const) string literal.
strncpy
by comparison will copy from that literal to the space put aside by the calloc
Upvotes: 0
Reputation: 6555
Assigning a name by "NAME"
creates a string literal which is defined as constant.
So you aren't allowed to change anything on the address, where name
is pointing to.
Its in c11 under 6.7.3
If an attempt is made to modify an object defined with a const-qualified type through use of an lvalue with non-const-qualified type, the behavior is undefined. If an attempt is made to refer to an object defined with a volatile-qualified type through use of an lvalue with non-volatile-qualified type, the behavior is undefined.
Peter.name[0] = 'a'
And thats exactly what your trying to do in this line.
So you would break your code. But the compiler fortunately avoids this.
Upvotes: 0