0

在这里,我想从输入读取数据到 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。

请帮我弄清楚我误解或不正确的地方

@all:感谢大家的帮助。我知道了。我读过一些帖子,解决方案是使用 #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;
}
4

5 回答 5

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

可能与您认为的方式不一致。字段之间存在编译器相关的填充。谷歌“结构填充”或类似的东西。

这应该向您显示字段偏移量:

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);
于 2013-09-10T17:02:10.147 回答
1

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

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

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

typedef struct dev
{
    short id;
    char name[5];
    int size;
} dev __attribute__ ((packed));
于 2013-09-10T17:02:26.437 回答
0

temp+1应该保持下一个开发者应该在的位置。这里sizeof(dev)是 12,所以temp +1基本上应该是,0x804a04c因为(0x804a040-0x804a04b)是为第一个开发者保留的。

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

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

总大小 12

于 2013-09-10T17:02:19.977 回答
0

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

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

于 2013-09-10T17:02:25.063 回答
0

您已经假定编译器已经组装了没有填充的结构。检查sizeof(dev),它不会是你认为的那样。

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

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

最好的解决方案可能是将输入单独复制映射到字段。

于 2013-09-10T17:03:52.060 回答