结构体定义及定义结构体变量:
struct Test
{
char a;
double b;
int c;
}t, *pt, tar[10];
void main()
{
struct Test t;
struct Test *pt;
struct Test tar[10];
}
匿名结构体—定义结构体同时定义结构体变量:
struct
{
char a;
double b;
int c;
}t;
void main()
{
t.a = 's';
t.b = 3.14;
printf("%c\n", t.a);
printf("%f\n", t.b);
}
上述代码结果:
结构体自引用:
typedef struct Node
{
int data;
struct Node *next;
}Node;
结构体变量的定义和初始化:
typedef struct Student
{
char name[10]; //falfkafklaflaasi
int age;
}Student;
void main()
{
Student s = {"abc", 10};
Student s1;
strcpy(s1.name, "xyz"); //memcpy
}
结构体内存对齐:
先介绍一下结构体的对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址处;
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有对齐数(含嵌套结构体的对齐数)的整数倍。
5.VS中默认的对齐数为8。
下面列举一些例子,过程见注释:
例1:
typedef struct Test
{
char a; //1 + 7
double b; //8
int c; //4 + 4
}Test;
void main()
{
printf("%d\n", sizeof(Test));
Test t;
t.a = 'A';
t.b = 12.34;
t.c = 100;
}
结果为:
例2:
typedef struct Test
{
char a; //1 + 3
int c; //4
double b; //8
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
例3:
#pragma pack(2)
typedef struct Test
{
char a; //1 + 1
double b; //8
int c; //4
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
例4:
#pragma pack(1)
typedef struct Test
{
char a; //1 + 1
short b; //2
int c; //4
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
注:如果设置对齐数为1,则直接将所有变量所占的字节数相加即可。
例5:
typedef struct Test
{
short a; //2 + 6
struct
{
int b; //4 + 4
double c; //8
char d; //1 + 7
};
int e; //4 + 4
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
注:最后一个变量仍然要凑够8个字节;
例6:
#pragma pack(2)
typedef struct Test
{
int a; //4
struct
{
double b[10]; //80
int c; //4
char d; //1 + 1
};
int e;//4
}Test;
结果为:
例7:
#pragma pack(4)
struct S4
{
char c1; //1 + 3
struct
{
double d; //8
char c; //1 +3
int i; //4
};
double e; //8
};
void main()
{
printf("%d\n", sizeof(struct S4));
}
例8:
#pragma pack(16)
struct S4
{
char c1; //1 + 7
struct
{
double d; //8
char c; //1 +3
int i; //4
};
double e; //8
};
void main()
{
printf("%d\n", sizeof(struct S4));
}
结果为:
注:16和8选择最小值8。
例9:
#pragma pack(16)
struct S3
{
double d; //8
char c; //1 +3
int i; //4
};
struct S4
{
char c1; //1 + 7
struct S3 s3; //16
struct
{
double d; //8
char c; //1 +3
int i; //4
};
double e; //8
};
void main()
{
printf("%d\n", sizeof(struct S4));
}
结果为:
例10:
#pragma pack(4)
struct S3
{
double d; //8
char c; //1 +3
int i; //4
};
struct S4
{
char c1; //1 + 3
struct S3 s3; //16
struct
{
double d; //8
char c; //1 +3
int i; //4
};
double e; //8
};
void main()
{
printf("%d\n", sizeof(struct S4));
}
结果为:
例11(关于位域)
typedef struct Test
{
char a : 1; //位域 位段 占八位中的一位
char b : 1;//和上面的元素占同一个字节
char c : 1;
}Test;
void main()
{
printf("%d\n", sizeof(Test));//一共占了一个字节其中的三位
}
结果为:
例12:
typedef struct Test
{
char a : 2; //位域 位段
char b : 3;
char c : 4;
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
例13:
//基本数据类型的自身对齐值:
//自定义类型的自身对齐值:
//程序的指定对齐值:
//程序的有效对齐值:
//位域不能跨字节存储
//位域不能跨类型存储
typedef struct Test
{
char a : 1;
int b : 1;
}Test;
void main()
{
printf("%d\n", sizeof(Test));
}
结果为:
注意:位域不能跨字节存储,位域也不能跨类型存储
枚举类型:
例如:
enum Day//星期
{
Mon = -100,
Tues,
Wed,
Thur = 100,
Fri,
Sat,
Sun
};
void main()
{
enum Day d = Mon;
printf("%d\n", Tues);//从有值的元素开始递增
printf("%d", Fri);//碰到下一个被赋值的元素,以该元素为起点,继续递增。
}
结果为:
联合(共同体)
这种类型定义的变量也包含一系列的成员,这些成员公用同一块空间(所以联合也叫共用体)
联合的特点:
1、一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
2、当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍(最后一个例子)。
例1
union Un
{
int i;
char c;
};
void main()
{
union Un un;
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
//下面输出的结果是什么?
un.i = 0x11223344; //44 33 22 11
un.c = 0x55; //55 33 22 11
printf("%x\n", un.i);
}
结果为:
例2(判断大小端)
bool check_modle()
{
int a = 0x01; //00 00 00 01
return *(char*)&a == 0x01;
}
void main()
{
if(check_modle())
printf("小端.\n");
else
printf("大端.\n");
}
结果为:
例3(用联合体判断大小端):
bool check_modle()
{
union
{
int a;
char c;
}un;
un.a = 0x01;
return un.c == 0x01;
}
void main()
{
if(check_modle())
printf("小端.\n");
else
printf("大端.\n");
}
结果为:
例4:
union Un1
{
char c[5]; //5
int i; //4
};
union Un2
{
short c[7];
int i;
};
void main()
{
printf("%d\n", sizeof(union Un1));//8
printf("%d\n", sizeof(union Un2));//16
}
结果为: