0

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?

1

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

2 Comments

"person Peter = {"peter", 19}; will copy the string "peter" into the name array." This works in c?
@Zaibis yes, it does. It's similar to doing e.g. char buf[64] = "peter";
0

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.

Comments

0

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

3 Comments

does strncpy change Peter.name as a pointer to a string literal to a pointer to a normal array?
@user2362322 strncpy copies Byte by Byte from source the chars into the destination memory area.
Great, I get what you mean. By using the function malloc, Peter.name now is a pointer variable pointing to a mutable array, where the manipulation of the char inside is allowed.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.