一、结构体的声明
1.1 结构的基础知识
结构是一些值的集合,这些值称为结构的成员变量,结构中的每个成员可以是不同类型的变 量
1.2 结构的定义
struct tag { member - list;//成员列表 }variable - list;//变量列表
示例:表述学生的信息
struct stu { char id[12]; char name[20]; char sex[10]; short age[4]; }
1.3 特殊定义
struct { int a ; char b ; float c ; } x ; struct { int a ; char b ; float c ; } * p ;
若p=&x,编译器会将上面的两个定义当成不同的两个类型
1.4 结构自引用
结构中包含一个结构体本身的成员。
struct Node { int date;//数据域 struct Node* next;//指针域 }; typedef struct Node { int date;//数据域 struct Node* next;//指针域 }Node;
1.5 结构体变量和初始化
struct stu { char id[12]; char name[20]; char sex[10]; short age[4]; } stu1;///定义类型同时定义变量stu1
struct stu stu2;//定义结构体变量stu2 struct stu stu3={“1234567890”,“张三”,“男”,21};//定义结构体变量时初始化 struct Point { int a; int b; }; struct Node { int data; struct Point p; struct Node* next; }n1 = { 10,{4,5},NULL}; //结构体嵌套初始化 struct Node n2 = { 20, {5, 6},NULL};//结构体嵌套初始化
1.6 结构体内存对齐
#include<stdio.h> struct s1 { char a1; int a2; char a3; }; struct s2 { char a1; char a3; int a2; }; int main() { printf("%d", sizeof(struct s1)); printf("%d", sizeof(struct s2)); }
输出
struct s1:
struct s2:
struct s3//结构体嵌套 { char c1; struct s2 s2; double d; }
输出
结构体对齐规则:
1. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数=成员的大小与编译器默认对齐数中的较小值
vs默认值为8,Linux没有默认对齐数,对齐数为成员大小
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处结构 体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
存在内存对齐的原因:
1.平台原因:不是所有的硬件平台都能访问任意地址上的任意数据;某些硬件平台只 能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
2.性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。为了访问未对齐的 内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。
注意:结构体的内存对齐是用空间来换时间。
1.7 修改默认对齐数
#include <stdio.h> #pragma pack(1)//设置默认对齐数为1 struct s1 { char c1; int i; char c2; }; int main() { //printf("%d\n", sizeof(struct s1)); //printf("%d\n", sizeof(struct s2)); printf("%d", sizeof(struct s1)); return 0; }
输出
#pragma pack() //取消设置的默认对齐数,还原为默认
1.8 结构体传参
struct S { int data [ 1000 ]; int num ; }; //结构体传参 void print1(struct S s) { printf("%d\n", s.num); } //结构体地址传参 void print2(struct S* ps) { printf("%d\n", ps->num); } int main() { struct S s = { {1,2,3,4},100 }; print1(s); print2(&s) return 0; }
输出