将结构类型转换为整数时出错

时间:2012-09-18 19:57:11

标签: c casting

我收到错误

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

3 个答案:

答案 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;