3

我收到错误

 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 位分配给整数。

4

4 回答 4

5
var = (U32)str;

因为str是结构类型的对象,您不能将结构对象转换为算术类型的对象。C 不允许您执行这种转换。

如果您想将结构对象作为整数访问,您可以创建结构和U32.

请注意,公共构造var = *(U32 *) str;是 C 中未定义的行为。它违反了别名和对齐规则。

于 2012-09-18T19:58:27.627 回答
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;
}

我想我的回答为时已晚,但试图解释。

于 2013-03-18T19:31:13.353 回答
2

你认为演员阵容会产生什么结果?您总是可以将它的地址转换为指向 int 的指针并取消引用它......但是您确定可以安全地这样做(不,您不能)?结构成员对齐是否有一天会咬你(答案是“可能,是的,这取决于”)?

此外,从 C99 标准:

C99 §6.7.2.1,第 10 段:“单元内位字段的分配顺序(高位到低位或低位到高位)是实现定义的。”

于 2012-09-18T20:00:58.700 回答
1

这并不总是一件愚蠢的事情。就我而言,我有一个需要通过网络连接发送的结构。数据必须以字节形式通过 SPI 总线发送,因此必须一次访问一个字节的结构。我使用这个定义来访问每个字节。您必须了解平台的字节顺序才能正确执行此操作。此外,您必须确保您的结构是__PACKED(另请参见:C/C++:强制位字段顺序和对齐),因此编译器不会插入任何填充块或对齐块。如果任何位成员跨越字节边界,这也将不起作用(至少,对于 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;
于 2014-01-10T14:22:41.470 回答