0

我有以下代码:

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

编译器给了我该行的“BAD ACCESS”错误消息

Peter.name[0] = 'a'

但以下行似乎不错

Petercp.name = "hello";

似乎 person.name 的数组是一个指向常量的指针。我下结论对吗?

而且,如果我将结构内的数组声明为

char name[];

我再次被允许为

Peter.name[0] = 'a'

这是为什么?

4

3 回答 3

4

当你这样做时person Peter = {"peter", 19};,你指向name一个字符串文字“peter”。

Peter.name[0] = 'a'试图改变 1.name指向的元素。修改字符串文字是未定义的行为,在您的情况下会导致崩溃。实际上,字符串文字通常加载到内存的只读部分中。

另一方面,Petercp.name = "hello";只是将指针更改为指向其他地方,这很好。

如果您将 name 成员声明为char name[64]然后是初始值设定项

  person Peter = {"peter", 19};

将字符串“peter”复制到name数组中。name 数组只是一个普通的 char 数组,您可以在其中更改各个元素。

于 2013-09-26T13:01:49.810 回答
0

分配一个名称通过"NAME"创建一个定义为常量的字符串文字。因此,您不得更改name指向的地址上的任何内容。

它在 6.7.3 下的 c11

如果尝试通过使用具有非 const 限定类型的左值来修改使用 const 限定类型定义的对象,则行为未定义。如果尝试通过使用具有非 volatile 限定类型的左值来引用使用 volatile 限定类型定义的对象,则行为未定义。

Peter.name[0] = 'a'

这正是你在这条线上想要做的。

所以你会破坏你的代码。但幸运的是,编译器避免了这种情况。

于 2013-09-26T13:04:21.390 回答
0

因为您没有为 peter 声明任何空间,所以 Peter.name[0] 不存在。

当您使用常量字符串进行初始赋值时,编译器会将常量字符串值分配给它,并且您不能更改常量。

以下将起作用:

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

这里的区别在于直接Peter.name = "hello"指向Peter.name(const) 字符串文字。 strncpy相比之下,将从该文字复制到由calloc

于 2013-09-26T12:58:49.647 回答