2

所以在我的代码中,我在头文件中定义了以下结构:

测试.h:

#ifndef TEST
#define TEST 
typedef struct struct1 {
    uint8_t a;
    uint16_t b;
    uint16_t c;
} struct1;

typedef struct struct2 {
    uint8_t a;
    uint8_t b;
    uint8_t c;
    uint8_t d;
    uint8_t e;
    struct struct1 f;
} struct2;
void doStuff(struct struct2 * s);
#endif

当我声明一个 struct2 并使用指向它的指针调用一个函数时,在函数内部分配的值与在该函数外部读取的值不匹配

主.c:

#include <stdint.h>
#include <stdio.h>
#include "test2.h"
#include "test.h"
int main(){
    struct struct2 s;
    s.a=0;s.b=0;s.c=0;s.e=0;
    printf("Main's s's size: %d\n", sizeof(s));
    doStuff(&s);
}

测试.c:

#include <stdint.h>
#include <stdio.h>
#include "test.h"
void doStuff(struct struct2 * s){
    printf("doStuff's size: %d\n", sizeof(*s));
}

测试2.h:

#pragma pack(1)

打印它们的大小时,doStuff 内部的 sizeof(*s) 返回 12,而在主函数 sizeof(s) 内部返回 10。当比较每个内部值的地址时,sa 到 se 匹配函数内部和外部,sf 和sfa一关,sfb和sfc二关。

知道这里发生了什么吗?

(注意:问题已被关闭,因为我不认为它是重复的。真正的问题源于 test2.h 使用 '#pragma pack(1)'。移动 test2.h 的#include在 test.h 之后使其按预期工作。要在 GCC 4.4 下运行上面的“gcc -o test test.c main.c”)

4

3 回答 3

1

有一个概念叫做“结构填充”。用简单的话来说,它说 uint16_t 只能占用 2 的倍数的内存地址。char 和 uint8_t 可以占用 1 的倍数的任何内存。所以以这种方式调整 有时会留下空焊盘 所以当我们使用 sizeof () 它还计算这些空焊盘。

于 2013-05-16T04:43:25.530 回答
0

我很高兴回答你的问题。主要思想是关于“内存对齐”。您可以通过 Google 搜索有关“内存对齐”的内容。

每个编译器都有不同的结果。在 Visual Studio 2012 中,我得到的结果与你的不同。

在这里,我得到了另一个关于这个问题的网站。也许它可以帮助你。 为什么这两个结构的大小不同?

于 2013-05-16T02:13:52.290 回答
0

我无法重现您的结果(您的工作代码会很有帮助)。这是我的,它打印 ((gcc-4.6.3 release with patch [build 20121012 by perlmingw.sf.net]) 4.6.3)

$ ./structs
main: 12 12
0 0 0 0 0 0 0 0
0 1 2 3 4 6 8 10
doStuff: 12 12
0 0 0 0 0 5 6 7

这对我来说看起来非常好。s 的大小为 12 个字节,struct2 的大小也是如此。将所有字段初始化为零后,它们为零。结构开头的偏移量是可以的(基于请求的类型),知道 C 结构对齐是基于结构中最大尺寸的本机类型。也就是说,你在 struct1 中有一个 uint16_t,因此该结构必须与 16 位字边界对齐,这解释了为什么 f 从偏移量 6 而不是 5 开始。

一旦doStuff返回,我得到了正确的值doStuff

#include <stdio.h>
#include <stdint.h>
#include <stddef.h>

typedef struct struct1 {
  uint8_t a;
  uint16_t b, c;
} struct1;

typedef struct struct2 {
  uint8_t a, b, c, d, e;
  struct struct1 f;
} struct2;

void doStuff(struct struct2 * s)
{
  printf("doStuff: %lu %lu\n", sizeof(*s), sizeof(struct struct2));  
  s->f.a = 5; s->f.b = 6; s->f.c = 7;
}

int main(int argc, char** argv)
{
  struct struct2 s;

  printf("main: %lu %lu\n", sizeof(s), sizeof(struct struct2));
  s.a=s.b=s.c=s.d=s.e=s.f.a=s.f.b=s.f.c=0;
  printf("%u %u %u %u %u %u %u %u\n", s.a,s.b,s.c,s.d,s.e,s.f.a,s.f.b,s.f.c);
  printf("%u %u %u %u %u %u %u %u\n",
     offsetof(struct struct2, a), offsetof(struct struct2, b),
     offsetof(struct struct2, c), offsetof(struct struct2, d),
     offsetof(struct struct2, e), offsetof(struct struct2, f.a),
     offsetof(struct struct2, f.b), offsetof(struct struct2, f.c));
  doStuff(&s);
  printf("%u %u %u %u %u %u %u %u\n", s.a,s.b,s.c,s.d,s.e,s.f.a,s.f.b,s.f.c);
  return 0;
}
于 2013-05-16T05:35:15.663 回答