struct xx {
long long a;
char b;
int c;
char d[2];
static int e;
};
int main(){
struct xx x;
printf("%ld\n", sizeof(x.a)); //8
printf("%ld\n", sizeof(x.b)); //1 + 3 = 4
printf("%ld\n", sizeof(x.c)); //4
printf("%ld\n", sizeof(x.d)); //2 + 6 = 8
printf("%ld\n", sizeof(x.e)); //4
printf("%ld\n", sizeof(x)); //24 = 8 + 4 + 4 + 8
printf("%p\n", &(x.a)); //007DFCEC
printf("%p\n", &(x.b)); //007DFCF4
printf("%p\n", &(x.c)); //007DFCF8
printf("%p\n", &(x.d[0])); //007DFCFC
printf("%p\n", &(x.d[1])); //007DFCFD
printf("%p\n", &(x.e)); //由于static变量分配在全局区,不在结构体的空间内,这一句报错
}
只有在C++中结构体中才能含有静态数据成员,而C中结构体中是不允许含有静态数据成员的
typedef struct{
char a;
int b;
short c;
}A;
int main(){
A aa;
printf("%ld\n", sizeof(aa.a));//1 + 3
printf("%ld\n", sizeof(aa.b));//4
printf("%ld\n", sizeof(aa.c));//2 + 2
printf("%ld\n", sizeof(aa));//12
printf("%p\n", &(aa.a));//00CFFCEC
printf("%p\n", &(aa.b));//00CFFCF0
printf("%p\n", &(aa.c));//00CFFCF4
}
typedef struct
{
char a;
short b;
int c;
}B;
int main(){
B bb;
printf("%ld\n", sizeof(bb.a));//1 + 1
printf("%ld\n", sizeof(bb.b));//2
printf("%ld\n", sizeof(bb.c));//4
printf("%ld\n", sizeof(bb));//8
printf("%p\n", &(bb.a));//00E6F858
printf("%p\n", &(bb.b));//00E6F85A
printf("%p\n", &(bb.c));//00E6F85C
}
struct Date {
char a;
int b;
long long c;
char d;
};
int main() {
struct Date date[2][10];
struct Date dd;
printf("%ld\n", sizeof(dd.a));//1 + 3
printf("%ld\n", sizeof(dd.b));//4
printf("%ld\n", sizeof(dd.c));//8
printf("%ld\n", sizeof(dd.d));//1 + 7
printf("%ld\n", sizeof(struct Date));//24
printf("%p\n", &(dd.a));//0093F9A8
printf("%p\n", &(dd.b));//0093F9AC
printf("%p\n", &(dd.c));//0093F9B0
printf("%p\n", &(dd.d));//0093F9B8
// 说明结构体最后的d占了8字节
printf("%p\n", &(date[0][0].d)); // 00F5F78C
printf("%p\n", &(date[0][1].a)); // 00F5F794
}
struct sdate {
int year;
int month;
int day;
};
struct Student {
char s_id[10];
char s_name[8];
struct sdate birthday;
double grade;
};
int main(){
printf("%ld\n", sizeof(struct Student));//40
return 0;
}
struct Person {
const char* name;
int age;
};
int main(){
printf("%ld\n", sizeof(struct Person)); // 8
struct Person p = {"shen12", 22};
printf("%ld\n", sizeof(p)); // 8
return 0;
}
空结构体
struct x{
};
int main(){
// C++ : 1,其实是占位符
// C : 0
printf("%ld\n", sizeof(struct x));
return 0;
}
不含任何成员变量且没有虚函数的存在:sizeof(对象)=1。解释——虽然什么都没有存,但是如果完全不分配空间的话,先定义一个对象再定义一个对象,如果对象不占空间的话,那么这两个对象起始地址就会一样,(除了联合体类型外,都不允许发生这样的情况)。分配最小的单位是1个字节——就是为了占地方,没有其他作用
pragma pack(n)改变内存对齐方式
关于改变内存对齐方式总结:
总结:
个人总结: 当放入一个结构体成员时,该成员的的起始地址相对于结构体首地址的偏移量必须是该成员大小的整数倍;整个结构体的大小是最大基本数据类型的整数倍。
如何不定义结构体变量计算结构体成员的偏移量?
#define offset(type, elem) (size_t)(&((type*)0)->elem)
struct Person {
char* name;
int age;
double weight;
};
int main(){
int dist1 = offset(struct Person, name);//0
int dist2 = offset(struct Person, age);//4
int dist3 = offset(struct Person, weight);//8
}
为什么要字节对齐?
cpu把内存当成是一块一块的,块的大小可以是2,4,8,16 个字节,因此CPU在读取内存的时候是一块一块进行读取的,块的大小称为(memory granularity)内存读取粒度。如果数据紧密排列,可能会出现cpu读取时,可能不是从每个数据的起始地址读取的,读取完后还要对读取的内存拆分后再组合,才能取出我们想要的某个数据
struct Data {
int a;
char b;
short c;
double d;
};
printf("%d\n", (char*)&(((struct Data*)0)->c) - (char*)&((struct Data*)0)->a)