我有以下代码:
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'
为什么?
答案 0 :(得分:4)
执行person Peter = {"peter", 19};
时,将name
指向字符串文字“peter”。
Peter.name[0] = 'a'
尝试更改name
所指向的1.元素。修改字符串文字是未定义的行为,在您的情况下,它会导致崩溃。在实践中,字符串文字通常被加载到内存的只读部分。
另一方面,执行Petercp.name = "hello";
只是将指针更改为指向其他位置,这很好。
如果您将名称成员声明为char name[64]
,那么初始值设定项
person Peter = {"peter", 19};
会将字符串“peter”复制到name
数组中。 name数组只是一个普通的char数组,您可以在其中更改各个元素。
答案 1 :(得分: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
答案 2 :(得分:0)
按"NAME"
分配名称会创建一个字符串文字,定义为常量。
因此,您无法更改name
指向的地址上的任何内容。
在c11下6.7.3
如果尝试通过使用具有非const限定类型的左值来修改使用const限定类型定义的对象,则行为未定义。如果尝试通过使用具有非volatile限定类型的左值来引用使用volatile限定类型定义的对象,则行为是未定义的。
Peter.name[0] = 'a'
这就是你想要在这一行中做的事情。
所以你会破坏你的代码。但幸运的是,编译器避免了这种情况。