因此,在我的代码中,我在头文件中定义了以下结构:
test.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并使用指向它的指针调用函数时,在函数内分配的值与在该函数外部读取的值不匹配
main.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);
}
test.c的:
#include <stdint.h>
#include <stdio.h>
#include "test.h"
void doStuff(struct struct2 * s){
printf("doStuff's size: %d\n", sizeof(*s));
}
test2.h:
#pragma pack(1)
当打印它们的尺寸时,doStuff内的sizeof(* s)返回12,而main函数sizeof(s)内部返回10.当比较每个内部值的地址时,sa到se匹配函数内部和外部,sf和sfa是一个关闭,sfb和sfc是两个关闭。
知道这里发生了什么吗?
(注意:问题已被关闭,因为我不相信它是重复的。真正的问题源于test2.h使用'#pragma pack(1)'。移动#include of在test.h之后的test2.h使它按预期工作。要运行上面的'gcc -o test test.c main.c',在GCC 4.4下)
答案 0 :(得分:1)
有一个名为“结构填充”的概念。简单来说,它表示uint16_t只能占用2的倍数的内存地址.Char和uint8_t可以占用任何内存,因为它们具有1的倍数。所以以这种方式调整有时候还有空的垫子所以当我们使用sizeof时()它也计算这些空垫。
答案 1 :(得分:0)
我很高兴回答你的问题。 主要思想是关于“记忆对齐”。您可以通过Google搜索“内存对齐”的内容。
每个编制者都有不同的结果。在Visual Studio 2012中,我得到了与您不同的结果。
我在这里得到另一个关于这个问题的网站。也许它可以帮到你。 Why the size of these two structs are different?
答案 2 :(得分:0)
我无法重现您的结果(您的工作代码会有所帮助)。这是我的,打印((gcc-4.6.3发布补丁[build by 2012 of 2012 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;
}