我收到错误
error: aggregate value used where an integer was expected
编译此代码:
#include <stdio.h>
typedef unsigned long U32;
typedef struct hello_s
{
U32 a:8;
U32 b:24;
}hello_t;
int main()
{
hello_t str;
U32 var;
str.a = 0xAA;
str.b = 0xAAA;
var = (U32)str;
printf("var : %lX\n", var);
return 0;
}
有人可以解释错误的含义,以及我做错了什么。
编辑:我知道这是一个愚蠢的事情。我想知道的是为什么编译器会为此而哭泣。为什么不能只将前32位分配给整数。答案 0 :(得分:5)
var = (U32)str;
因为str
是结构类型的对象,并且您无法将结构对象转换为算术类型的对象。 C不允许您执行此类转换。
如果要将结构对象作为整数访问,可以创建结构和U32
的联合。
请注意,公共构造var = *(U32 *) str;
在C中是未定义的行为。它违反了别名和对齐规则。
答案 1 :(得分:3)
嗯,我认为不应该错误地认为C99规范是违反语言标准的。
该标准仅表示转换结果可能无法在不同的机器/架构中移植。
只要您已将程序编码为适用于特定架构,就可以了。
例如,我将数据结构DataStr_t的选择性成员分组,唯一标识对象(即密钥),打包到另一个结构中,比如DataStrKey_t。我将确保sizeof(DataStrKey_t)等于sizeof(uint64),并且出于所有实际目的,将其用作uint64,因为它易于处理。
我也经常做以下操作:
memcmp(&var_uint64, &var_DataStructKey, sizeof(uint64));
如果您使用计算机上的密钥读取访问权限或写入访问对象,则转换产生的值是可预测的,并且按位对齐是一致的。 好吧,如果你将“只有这个数据”移动到另一台机器(实际上没有写入数据)并尝试阅读它,事情可能会中断。
您的程序稍作修改,以获得更多解释和成功编译: 在这里,只要LINE_A和LINE_B在同一台机器上执行,结果总是可预测的。 但是如果你将(var_uint64,var_DataStructKey)写入文件并从另一台机器读取它,然后对这些填充的值执行LINE_B,则比较“可能”失败。
#include <stdio.h>
#include <string.h>
typedef unsigned long U32;
typedef struct hello_s
{
U32 a:8;
U32 b:24;
}hello_t;
int main()
{
hello_t str;
U32 var;
str.a = 0xAA;
str.b = 0xAAA;
var = *(U32 *)(&str); //LINE_A
if(0 == memcmp(&var, &str, sizeof(U32))) //LINE_B
printf("var : %lu\n", var);
return 0;
}
我想我的答案为时已晚,但试图解释。
答案 2 :(得分:0)
这并不总是一件蠢事。在我的情况下,我有一个结构,我需要通过网络连接发送。必须以字节形式通过SPI总线发送数据,因此必须一次一个字节地访问结构。我用这个define来访问每个字节。您必须了解平台的字节顺序才能正确执行此操作。此外,您必须确保结构为__PACKED(另请参阅:C/C++: Force Bit Field Order and Alignment),因此编译器不会插入任何填充块或对齐块。如果任何位成员跨越字节边界,这也将无效(至少,Microchip XC16编译器没有)。
typedef unsigned char byte;
#define STRUCT_LB(x) ((byte *)(&x))[0]
#define STRUCT_HB(x) ((byte *)(&x))[1]
更好的方法是将结构定义为位域和字节数组的并集,如下所示:
typedef unsigned char byte;
typedef struct {
union {
struct __PACKED {
byte array[2];
} bytes;
struct __PACKED {
byte b0: 1;
byte b1: 1;
byte b2: 1;
byte b3: 1;
byte b4: 1;
byte other: 3;
byte more: 6;
byte stuff: 2;
} fields;
};
} MyData;