使用struct进行类型转换

时间:2013-09-10 16:50:45

标签: c struct

这里我想读取输入到struct dev的数据,所以我使用temp =(dev *)输入从char *转换为dev *。在我的机器上,行 printf(“%p \ n”,temp); 打印出0x804a040,如果为真,则行 printf(“%p \ n”,temp + 1) ); 应打印出0x804a04b,但它打印0x804a04c。行 printf(“%p \ n”,& temp-> size); 应打印出0x804a047,但它打印为0x804a048。

Plz帮助我弄清楚我误解或错误

@all:感谢所有人的帮助。我知道了。我读过一些帖子和solusion正在使用#paragma pack(1)或者像这样的指令。但它也是劝阻,因为它会减慢前任的处理速度。那么,还有其他任何想法。

感谢!

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

typedef struct dev
{
    short id;
    char name[5];
    int size;
} dev;

char input[] = {  0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x09, 0x00, 0x00, 0x00,
                  0x00, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00,
                  0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00,
                  0x03, 0x00, 0x65, 0x67, 0x03, 0x00, 0x43, 0x43, 0x00, 0x43, 0x00 };

int
main (int argc, char *argv[])
{
    dev* temp;
    temp = (dev*)input;

    printf("%p\n", temp);
    printf("%p\n", temp+1);

    printf("%d\n", temp->id);
    printf("%p\n", &temp->name[4]);
    printf("%p\n", &temp->size);
    temp++;
    printf("%d\n", temp->id);

    return 0;
}

5 个答案:

答案 0 :(得分:3)

typedef struct dev
{
    short id;
    char name[5];
    int size;
} dev;

可能与您认为的不一致。有编译器相关的填充 在田野之间。谷歌“struct padding”或类似的东西。

这应该显示字段偏移量:

dev foo;
printf("offset of id is %d\n", (char *)&foo.id - (char *)&foo);
printf("offset of name is %d\n", (char *)&foo.name[0] - (char *)&foo);
printf("offset of size is %d\n", (char *)&foo.size - (char *)&foo);

答案 1 :(得分:1)

答案非常简单:每个结构项的大小总和为11个字节,但出于性能原因,“int size”被置于可被4整除的地址。

所以'结构中的大小偏移应该是7但是为8(因为8是可以被4整除的更接近的数字),所以最终大小为12。

您可以强制编译器打包struct。对于gcc,你可以这样做:

typedef struct dev
{
    short id;
    char name[5];
    int size;
} dev __attribute__ ((packed));

答案 2 :(得分:0)

temp+1应该保留下一个开发者的位置。此处sizeof(dev)为12,因此temp +1应该基本上位于0x804a04c,因为(0x804a040-0x804a04b)是为第一个开发者保留的。

大小为12,因为为了优化,编译器分配的内存为4的倍数。这是32位架构中的典型优化技术。 实际上你的内存分配很可能是ike:

<char><char><char><char>
<char><short><padding>
<int>

总大小为12

答案 3 :(得分:0)

对齐。数据通常会在字大小边界上对齐,因为它是处理器读取和提高性能的“自然”大小。

在这种情况下,结构的大小为11个字节。填充到12。

答案 4 :(得分:0)

您已经假定编译器已经组装了没有填充的结构。检查sizeof(dev),这不符合您的想法。

填充的目的是在字(4字节)边界上对齐int成员字段 - 因为short是2而“name”是5,所以在name和{之间有一个填充字节{1}}。

一种解决方案是使size 6个字节。这并不能保证一些奇怪的编译器不会做一些奇怪的事情 - 但这似乎不太可能。您还可以使用编译器特定的“pack”编译指示。

最佳解决方案可能是将输入复制映射到字段中。