使struct成员虚拟

时间:2014-11-13 10:55:29

标签: c struct

我想将一大块内存解析为结构。问题是成员不是一个接一个,而且有一些填充。

struct foo {
  unsigned int a; // @ 0
  unsigned int junk; // @ 0x4
  unsigned int b; // @ 0x08
  unsigned int more_junk;
  .........
};

我不想为每个我拥有的垃圾分配结构中的每个成员。我知道这对工会来说是可能的,但对结构不确定。

更新 我将再举一个更明确的例子:

#include <stdio.h>
#include <string.h>

main()
{

    struct w {
        unsigned long a;
        unsigned long b;
        unsigned long c;
        unsigned long d;
    };

    struct w *q;

    unsigned long array[] = 
    {
        0x11111111, 
        0x22222222, 
        0x33333333, 
        0x44444444
    };

    q = (struct w*)array;

    printf("%x\n", q->a);
    printf("%x\n", q->b);
    printf("%x\n", q->c);
    printf("%x\n", q->d);

}

输出结果为:

11111111
22222222
33333333
44444444

让我们说3是垃圾。同样的例子:

#include <stdio.h>
#include <string.h>

main()
{

    struct w {
        unsigned long a;
        unsigned long b;
        unsigned long d;
    };

    struct w *q;

    unsigned long array[] = 
    {
        0x11111111, 
        0x22222222, 
        0x33333333, 
        0x44444444
    };

    q = (struct w*)array;

    printf("%x\n", q->a);
    printf("%x\n", q->b);
    printf("%x\n", q->d);

}

输出结果为:

11111111
22222222
33333333

但它应该是:

11111111
22222222
44444444

3 个答案:

答案 0 :(得分:1)

  

有一些填充。

事实上。这就是为什么结构不适合用于内存映射目的的危险。

  

问题在于成员不是一个接一个   我不想为每个我拥有的垃圾分配结构中的每个成员

不太清楚你的意思。如果您不想,您不必分配任何内容。但是,您需要声明空间以获取垃圾字节的位置。只需在结构中声明一个虚拟变量,您稍后会忽略该变量,就像在第一个结构示例中那样。

没有办法解决这个问题,唯一的选择是使用完全不同的数据结构,例如原始数据的普通字节数组。但这很难让你的程序更容易阅读。

但是,如果不需要保留垃圾字节,即你进行内存映射,而只是一些&#34; cherry pick&#34;您感兴趣的数据,那么您在结构中不需要垃圾字节。但是你必须手动分配每个成员,而不是使用memcpy。

  

我知道工会可以做到这一点

不,不,我认为你误解了工会是如何运作的。

答案 1 :(得分:0)

从你的问题:

  
      
  1. 会员不是一个接一个:我建议您重新排列结构的成员,以便它们与您要复制的内存块同步。
  2.   
  3. 有一些填充:在定义结构时,可以使用__attribute__((__packed__))关键字阻止编译器填充,这会导致编译器停止填充。
  4.   
struct  __attribute__((__packed__)) foo {
    unsigned int a; // @ 0
    unsigned int junk; // @ 0x4
    unsigned int b; // @ 0x08
    unsigned int more_junk;
    .........
};

在此之后,您可以使用memcpy()将内存块的内容复制到struct foo variable,或者如果它是struct foo *ptr,则直接指向内存。

有关struct padding和packing的更多信息,请参阅:Structure padding and packing

答案 2 :(得分:0)

嗨,GCC 中的朋友,您可以在结构中使用它进行填充:

Type : Width;

这个变量没有名字;

struct foo {
    unsigned int a: 4;
    unsigned int: 4; //junk;
    unsigned int b: 1;
    unsigned int: 7; //more_junk;
};

这个结构体使用 2 字节的 sram 内存。

例如:

main() {

    struct w {
        unsigned long a;
        unsigned long b;
        unsigned long;
        unsigned long d;
    };

    struct w * q;

    unsigned long array[] = {
        0x11111111,
        0x22222222,
        0x33333333,
        0x44444444
    };

    q = (struct w * ) array;

    printf("%x\n", q -> a);
    printf("%x\n", q -> b);
    printf("%x\n", q -> d);

}