16位系统:long是4字节,int是2字节
32位系统:long是4字节,int是4字节
64位系统:long是8字节,int是4字节
c结构体 不能包含函数,但可以包含函数指针(就是个指针变量)
c++结构体可以包含函数;
struct StructA{
//返回值 (*函数名)(参数列表...)
int (*func_p) (int, int);//函数指针
int a;
}
对齐规则
:
结构体中一个变量占用 n 个字节,则该变量的起始地址必须能够被 n 整除,即:
存放起始地址 % n = 0
,对于结构体而言,这个 n 取其成员中的数据类型占空间的值最大的那个。(这里n可以称为对齐值)
补充:
结构体的长度必须为结构体的实际对齐值(自身对齐值和编译器默认对齐值中最小的一个)的整数倍,不够就补空字节。
为什么要字节对齐
内存空间是按照字节来划分的,从理论上说对内存空间的访问可以从任何地址开始,但是在实际上不同
架构
的 CPU 为了提高访问内存的速度,就规定了对于某些类型的数据只能从特定的起始位置开始访问。这样就决定了各种数据类型只能按照相应的规则在内存空间中存放,而不能一个接一个的顺序排列。
举个例子,比如有些平台访问内存地址都从偶数地址开始,对于一个 int 型(假设 32 位系统),如果从偶数地址开始的地方存放,这样一个读周期就可以读出这个 int 数据,但是如果从奇数地址开始的地址存放,就需要两个读周期,并对两次读出的结果的高低字节进行拼凑才能得到这个int 数据,这样明显降低了读取的效率。
typedef struct structA A;
#include <stdio.h>
//#pragma pack(4)
struct A {//8
char a;//1
long b;//4
};
struct B {//16?
char a;//1
struct A b;//8
long c;//4
};
struct C {//24
char a;//1
struct A b;//8
double c; //8 Change “long” to “double” in struct B
};
struct D {
char a;//1
struct A b;//8
double c;//8
int d; //4 Add “int” in struct C
};
struct E {
char a;
int b;
struct A c;
double d;
};
void main(void)
{
struct C c = { 'a', { 'b', 10 }, 11.1 };
printf("long's size: %d\n", sizeof(long));
printf("int's size: %d\n", sizeof(int));
printf("double's size: %d\n", sizeof(double));
printf("A's size: %d\n", sizeof(struct A));
printf("B's size: %d\n", sizeof(struct B));
printf("C's size: %d\n", sizeof(struct C));
printf("C's address: %#d\n", &c);
printf("C.a's address: %#d\n", &c.a);
printf("C.b's address: %#d\n", &c.b);
printf("C.c's address: %#d\n", &c.c);
printf("D's size: %d\n", sizeof(struct D));
printf("E's size: %d\n", sizeof(struct E));
getchar();
}