结构基础知识
在C语言中结构体是一种数据结构。结构体可被声明为变量,指针或者数组等;同时,也是一些元素的集合,这些元素被称为结构体成员,且这些成员可以是不同的类型,成员一般用名字访问
struct Stu //Stu为结构体标签 { char name[20]; int age; charsex[5]; char tele[12]; char addr[30];//成员 }stu1,stu2; //stu1和stu2均为全局的结构体变量, int main() { struct Stu stu;//创建结构体变量 }
匿名结构体,将结构体标签省略,则必须在后面申明全局变量,但是也存在类型不同的问题
struct { char name[20]; int age; charsex[5]; char tele[12]; char addr[30];//成员 }stu1; struct { char name[20]; int age; charsex[5]; char tele[12]; char addr[30];//成员 }*pstu; //两结构体成员一模一样 int main() { pstu=&stu1;/*error,两个类型不同,因为是匿名的结构体类型,通过其创建的变量编译器会认为他们是不同的类型*/ }
typedef简化struct
struct Stu { char name[20]; int age; charsex[5]; char tele[12]; char addr[30];//成员 }stu1,arrstu[10],*pstu; typedef struct Stu stu;/*如果typedef加在结构体前面,则后面的全局变量则表示为这个结构体的新名字*/ int main() { stu stu2;//省略struct stu arr2[10]; stu *pstu; return 0; }
结构体成员
1.直接访问
struct stu { char name[20]; int age; char sex[5]; char tele[12]; char addr[30];//成员 }; typedef struct stu stu; int main() { stu stu;//结构体变量 //stu.name="bit";//error,不能给常量赋值 strcpy(stu.name,"aaa"); stu.age=10; printf("name=%s",stu.name); printf("age=%d",stu.age); return 0; }
2.间接访问
-> 用于结构体指针
. 用于结构体变量
struct stu { char name[20]; int age; char sex[5]; char tele[12]; char addr[30];//成员 }; typedef struct stu* pstu; int main() { stu stu;//结构体变量 pstu pstu1=&stu; //strcpy((*pstu1).name,"aaa"); //(*pstu1).age=20; strcpy(pstu1->name,"aaa"); return 0; }
结构体自引
例1.错误的方式
struct A { char name[10]; int age; struct A sa; } int main() { struct A sa; }
用递归造成死循环,不断的自己引用自己
改正
struct A { char name[10]; int age; struct A *sa;//大小为一个确切的值,通过指针找到下一个 } int main() { struct A sa1; struct A sa2; struct A sa3; sa1.pa=&sa2; sa2.pa=&sa3; sa3.pa=NULL; }
若想用typedef改写,则
typedef struct A//结构体内部嵌套同类型指针,重命名不能是匿名的结构体 { char name[10]; int age; struct A *sa; }a; int main() { a sa1; a sa2; a sa3; sa1.pa=&sa2; sa2.pa=&sa3; sa3.pa=NULL; }
不完整声明
struct A { int i; struct B b; }; struct B { int i; struct A a; }; //不允许这种写法,会一直相互调用下去
改写为
struct B; struct A { int i; struct B *b; }; struct B { int i; struct A *a; };
结构体初始化
struct stu { char name[10]; int age; char sex[4]; char tel[12]; char add[20]; }; int main() { struct stu stu={"aaa",12,"male","123","xia"}; printf("%s\n",stu.name); printf("%d\n",stu.age); return 0; }
结构体中含有结构体的初始化
struct A { int a; char c; double d; }; struct stu { char name[10]; int age; char sex[4]; char tel[12]; char add[20]; struct A sa; }; int main() { struct stu stu={"aaa",12,"male","123","xian"};//不完全初始化 struct stu stu={"aaa",12,"male","123","xian",{1,‘w‘,12.34}};//sa前的成员不可省略 printf("%s\n",stu.name); printf("%d\n",stu.age); printf("%1f\n",stu.sa.d); return 0; }
结构体大小
struct s { int a; char c; couble d; }; struct s2 { int a; double d; char c; }; int main() { printf("%d\n",sizeof(struct s)); printf("%d\n",sizeof(struct s2)); return 0; } //输出16 24
存在内存对齐规则
- 第一个成员在与结构体变量偏移地址为0的地址处
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址
对齐数=编译器默认的一个对齐数与该成员大小的较小值
vs中默认8,linux默认4
3. 结构体总大小为最大对齐数(每个成员变量除了第一个成员都有个对齐数)的整数倍
4. 如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍出,结构体的整体大小就是所有最大对其数(含嵌套结构体的对齐数)的整数倍
struct A { double d; char c; short s; dpuble d2; }; int main() { printf("%d",sizeof(struct A));//24 printf("%d",offsetof(struct A,d));//0 }
offsetof是求每个类型对其的地址
时间: 2024-10-13 07:35:46