分配结构字段时,"错误:赋值给表达式,数组类型错误"(C)

Chi*_*096 31 c arrays string struct initialization

我是初学C程序员,昨天我学习了C结构的使用以及这些结构可能应用于特定问题的解决方案.然而,当我尝试使用我的C IDE(Codeblocks 16.01)来学习C编程的这个方面时,我遇到了一个奇怪的问题.代码如下:

#include <stdio.h>

#define N 30

typedef struct{
     char name[N];
     char surname[N];
     int age;
} data;

int main() {
     data s1;
     s1.name="Paolo";
     s1.surname = "Rossi";
     s1.age = 19;
     getchar();
     return 0;
}
Run Code Online (Sandbox Code Playgroud)

在编译期间,编译器(Windows下的GCC 4.9.3-1)向我报告了一个错误

"错误:赋值给表达式,数组类型错误"

在指导上

s1.name="Paolo" 
s1.surname="Rossi" 
Run Code Online (Sandbox Code Playgroud)

如果我这样做的话

data s1 = {"Paolo", "Rossi", 19};
Run Code Online (Sandbox Code Playgroud)

有用.我究竟做错了什么?

Sou*_*osh 41

你正面临着问题

 s1.name="Paolo";
Run Code Online (Sandbox Code Playgroud)

因为,在LHS中,您使用的数组类型不可分配.

为了详细说明,从C11章§6.5.16

赋值运算符应具有可修改的左值作为其左操作数.

并且,关于可修改的左值,来自章节§6.3.2.1

可修改的左值是一个没有数组类型的左值,[...]

您需要使用strcpy()复制到阵列中.

也就是说,data s1 = {"Paolo", "Rossi", 19};工作正常,因为这不是涉及赋值运算符的直接赋值.我们使用括号括起的初始化列表来提供对象的初始值.这遵循初始化定律,如章节§6.7.9中所述

每个大括号括起的初始化列表都有一个关联的当前对象.当没有指定时,根据当前对象的类型按顺序初始化当前对象的子对象:增加下标顺序的数组元素,声明顺序中的结构成员,以及union的第一个命名成员.[... ]

  • 如果我有`char *b = "Hello"`,并且如果我有`char c[] = "hello"`,两者都有效,如果对于第一种情况我做`b = "helloworld"`,它也有效,但是对于第二种情况,如果我做`c = "helloworld"`,那不是为什么? (4认同)
  • @SurajJain 这正是答案中所解释的。您不能分配给数组。 (2认同)

tek*_*aul 13

typedef struct{
     char name[30];
     char surname[30];
     int age;
} data;
Run Code Online (Sandbox Code Playgroud)

定义data应该是一个内存块,适合60个字符加上4个int*

[----------------------------,------------------------------,----]
 ^ this is name              ^ this is surname              ^ this is age
Run Code Online (Sandbox Code Playgroud)

这会在堆栈上分配内存.

data s1;
Run Code Online (Sandbox Code Playgroud)

作业只是复制数字,有时是指针.

这失败了

s1.name = "Paulo";
Run Code Online (Sandbox Code Playgroud)

因为编译器知道这s1.name是一个64字节长的结构的开始,并且"Paulo"是一个char [] 6个字节长(6个因为C字符串中的尾随\ 0)
因此,尝试将指向字符串的指针分配给字符串.

将"Paulo"复制结构中的结构中,将name"Rossi" 复制结构中surname.

memcpy(s1.name,    "Paulo", 6);
memcpy(s1.surname, "Rossi", 6);
s1.age = 1;
Run Code Online (Sandbox Code Playgroud)

你结束了

[Paulo0----------------------,Rossi0-------------------------,0001]
Run Code Online (Sandbox Code Playgroud)

strcpy做同样的事情,但它知道\0终止所以不需要硬编码的长度.

或者,您可以定义一个指向任何长度的char数组的结构.

typedef struct {
  char *name;
  char *surname;
  int age;
} data;
Run Code Online (Sandbox Code Playgroud)

这将创造

[----,----,----]
Run Code Online (Sandbox Code Playgroud)

现在这将有效,因为您使用指针填充结构.

s1.name = "Paulo";
s1.surname = "Rossi";
s1.age = 1;
Run Code Online (Sandbox Code Playgroud)

像这样的东西

[---4,--10,---1]
Run Code Online (Sandbox Code Playgroud)

其中4和10是指针.

*注意,整数和指针可以是不同的大小,上面的大小4是32位作为示例.


小智 12

请在此处查看此示例:访问结构成员

有人解释说,正确的方法是这样的:

strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);
Run Code Online (Sandbox Code Playgroud)