“错误:分配给带有数组类型错误的表达式”当我分配结构字段时(C)
Posted
技术标签:
【中文标题】“错误:分配给带有数组类型错误的表达式”当我分配结构字段时(C)【英文标题】:"error: assignment to expression with array type error" when I assign a struct field (C) 【发布时间】:2016-09-10 13:12:32 【问题描述】:我是一名初学者 C 程序员,昨天我学习了 C 结构体的使用以及这些结构体在解决具体问题方面的可能应用。然而,当我尝试使用我的 C IDE(代码块 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;
在编译过程中,编译器(Windows 下的 GCC 4.9.3-1)向我报告了一个错误,上面写着
“错误:赋值给数组类型错误的表达式”
关于指令
s1.name="Paolo"
s1.surname="Rossi"
如果我这样做了
data s1 = "Paolo", "Rossi", 19;
它有效。 我究竟做错了什么?
【问题讨论】:
您已经发现了赋值和初始化之间的区别之一。 你能说得更具体点吗?谢谢;) 你可以写s1 = (const data)"Paolo", "Rossi", 19;
【参考方案1】:
您在
中遇到问题 s1.name="Paolo";
因为,在 LHS 中,您使用的是 array 类型,它不是可赋值的。
详细说明,来自C11
,第 6.5.16 章
赋值运算符应该有一个可修改的左值作为其左操作数。
关于 可修改的左值,来自第 §6.3.2.1 章
一个可修改的左值是一个左值 没有数组类型,[...]
您需要使用strcpy()
来复制到数组中。
也就是说,data s1 = "Paolo", "Rossi", 19;
工作正常,因为这不是涉及赋值运算符的直接赋值。我们使用大括号括起来的初始化列表 来提供对象 的初始值。这遵循第 6.7.9 章中提到的初始化法则
每个用大括号括起来的初始化列表都有一个关联的当前对象。没有时 指定存在,当前对象的子对象按顺序初始化 到当前对象的类型:下标递增顺序的数组元素,结构 声明顺序的成员,以及工会的第一个命名成员。[....]
【讨论】:
如果我有char *b = "Hello"
,如果我有char c[] = "hello"
,两者都可以,如果第一种情况我做b = "helloworld"
,它也可以,但是对于第二种情况,如果我做c = "helloworld"
,为什么不这样呢?
@SurajJain 这正是答案中所解释的。您不能分配给数组。【参考方案2】:
请在此处查看此示例:Accessing Structure Members
有说明正确的做法是这样的:
strcpy(s1.name , "Egzona");
printf( "Name : %s\n", s1.name);
【讨论】:
这有一个额外的函数调用开销(编译器可以选择内联但通常不会),它执行循环而不是内联,并且如果您正在编译的机器不会消除此循环可以一次复制整个事物,它总是至少进行一次迭代。这似乎无法在不预处理源代码的情况下解决,因为 C 不会为您做这件事。char x[2] = 'h', 0; *(char (*)[2])&x = *(char (*)[2])&x;
应该比 strcpy(x, x, 2)
快得多,如果它是有效的 C。【参考方案3】:
typedef struct
char name[30];
char surname[30];
int age;
data;
定义 data
应该是一块内存,可以容纳 60 个字符加上 4 个 int(见注释)
[----------------------------,------------------------------,----]
^ this is name ^ this is surname ^ this is age
这会在堆栈上分配内存。
data s1;
作业只是复制数字,有时是指针。
失败了
s1.name = "Paulo";
因为编译器知道 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;
你最终得到
[Paulo0----------------------,Rossi0-------------------------,0001]
strcpy
做同样的事情,但它知道\0
终止,因此不需要硬编码长度。
或者,您可以定义一个结构,该结构指向任意长度的字符数组。
typedef struct
char *name;
char *surname;
int age;
data;
这将创建
[----,----,----]
这现在可以工作了,因为您正在用指针填充结构。
s1.name = "Paulo";
s1.surname = "Rossi";
s1.age = 1;
类似的东西
[---4,--10,---1]
其中 4 和 10 是指针。
注意:整数和指针可以是不同的大小,上面的大小4以32位为例。
【讨论】:
【参考方案4】:使用 strcpy() 函数来修改值。因为在 C 中无法直接为字符串赋值。(将显示 Not Assignable 错误)。
strcpy(s1.name, "New_Name");
【讨论】:
这与this other answer中的解决方案相同。以上是关于“错误:分配给带有数组类型错误的表达式”当我分配结构字段时(C)的主要内容,如果未能解决你的问题,请参考以下文章
SAP HANA SQL - 将单个列的多个结果行合并为单个行