“错误:分配给带有数组类型错误的表达式”当我分配结构字段时(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])&amp;x = *(char (*)[2])&amp;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)的主要内容,如果未能解决你的问题,请参考以下文章

JMeter 结果树显示 1 个请求失败

e信与酸酸结合开wifi使用路由器上网

SAP HANA SQL - 将单个列的多个结果行合并为单个行

在 linux 的 react-native(android) 连接问题上,无法连接远程调试器意外结束流

如何在 NUMA 机器上的不同节点上分配数组的一部分?

iPhone - 内存分配略有增加