结构基础知识

在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

存在内存对齐规则

  1. 第一个成员在与结构体变量偏移地址为0的地址处

  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址

   对齐数=编译器默认的一个对齐数与该成员大小的较小值

   vs中默认8,linux默认4

3.  结构体总大小为最大对齐数(每个成员变量除了第一个成员都有个对齐数)的整数倍

4.  如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍出,结构体的整体大小就是所有最大对其数(含嵌套结构体的对齐数)的整数倍

struct A{double d;char c;  short s;  dpuble d2;};int main(){printf("%d",sizeof(struct A));//24printf("%d",offsetof(struct A,d));//0}

offsetof是求每个类型对其的地址