C 结构体 联合体 typedef

时间:2022-09-05 21:00:42

C 结构体的定义

#include <stdio.h>
struct student
{
        int ID;
        char name[10];
        int age;
}; //注意这里的分号

int main()
{
        // 初始化
        struct student student1 = {1111,"Redhat",20};
        struct student student2 = {.ID = 1111,.name = "Debian",.age = 20};//C99才有
        struct student student3 = {1111,"BSD",.ID = 20,.age = 30}; //ID = 20

        //使用
        printf("%d,%s,%d \n",student1.ID,student1.name,student1.age);
        printf("%d,%s,%d \n",student2.ID,student2.name,student2.age);
        printf("%d,%s,%d \n",student3.ID,student3.name,student3.age);


}



chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
1111,Redhat,20 
1111,Debian,20 
20,BSD,30







结构体内存分配情况

小的遵循大的数据类型,存在浪费内存的情况

#include <stdio.h>#include <string.h>struct student{        unsigned char c1;        unsigned char c2;        unsigned int  i1;        unsigned char c3;        unsigned char c4;        unsigned char c5;        unsigned char c6;        unsigned int  i2;}; int main(){        printf("%ld \n",sizeof(struct student));        struct student student1;        memset(&student1,0x55,sizeof(struct student));        student1.i1 = 0x12345678;        student1.i2 = 0x23456789;        student1.c1 = 0x21;        student1.c2 = 0x22;        student1.c3 = 0x23;        student1.c4 = 0x24;        student1.c5 = 0x25;        student1.c6 = 0x26;        int *p = (int*) &student1;        for(int i = 0;i< sizeof(struct student)/4;i++)        {                printf("%p  %x \n",p,*p);                p++;        }}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out16 0x7ffc7913b1c0  55552221 0x7ffc7913b1c4  12345678 0x7ffc7913b1c8  26252423 0x7ffc7913b1cc  23456789 可以看到内存初始化就是0X55,第一个的4个字节存在了浪费



结构体,自定义数据类型:

#include <stdio.h>#include <string.h>struct student{        unsigned char c1:1;        unsigned char c2:3;        unsigned char c3:4;}; int main(){        printf("%ld \n",sizeof(struct student));        struct student student1;        student1.c1 = 1;        student1.c2 = 6;        student1.c3 = 14;        char *p = (char *)& student1;        printf("%x,%d,%d,%d \n",*p,student1.c1,student1.c2,student1.c3);}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out1 ffffffed,1,6,14




结构体嵌套:

#include <stdio.h>#include <string.h>struct man{        unsigned char  age;};struct student{        unsigned char name[20];        struct man a_man;}; int main(){        printf("%ld \n",sizeof(struct student));        struct student student1;        student1.a_man.age = 10;        printf("student age = %d \n",student1.a_man.age);}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out21 student age = 10



结构体数组,结构体嵌套

#include <stdio.h>#include <string.h>struct man{        char           name[20];        unsigned char  age;        unsigned char  heiget;};struct human{        struct man son;        int money;};int main(){        printf("%ld \n",sizeof(struct human));        /*      结构体数组      */        struct man people[3]={                {"奥巴马",50,170},                {"金正恩",44,166},                {"朴槿惠",33,155},        };        /*      结构体嵌套      */        struct human a_human;        a_human.son.age = 10;        printf("son age = %d \n",a_human.son.age);}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out28 son age = 10




结构体赋值

#include <stdio.h>#include <string.h>struct man{        char           name[20];        unsigned char  age;        unsigned char  height;};int main(){        struct man people1={"奥巴马",50,170};        struct man people2;        people2 = people1; //结构体的赋值,people1的内存赋值到了people2,二者相互独立!        //memcpy(&people2,&people1,sizeof(people1));        //相当于memcpy(&people2,&people1,sizeof(people1));        printf("%s,%d,%d \n",people2.name,people2.age,people2.height);        ///////////////////////////////////////////////////////        /*区别于数组        char str1[10] = {"Hello!"};        char str2[20];        str2 = str1;  //这是不允许的。数组的名仅是一个地址,不允许赋值。        //////////////////////////////////////////////////////        //这个不是赋值,这个只能是指向了那个地址        char str3[] = {"Hello !"};        char *p1 = str3;        char *p2 = p1;        */}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out奥巴马,50,170






结构体赋值里面的指针变量

#include <stdio.h>#include <stdlib.h>#include <string.h>struct man{char           *name;unsigned char  age;unsigned char  height;};int main() {struct man people1={"朴槿惠",40,170};struct man people2;people2 = people1;//结构体赋值printf("%s,%d,%d \n",people2.name,people2.age,people2.height);people2.name = "王麻子"; //指针指向常量"王麻子"printf("%s,%d,%d \n",people2.name,people2.age,people2.height);/*结构体指针*/struct man people3;people3.name = malloc(20);strcpy(people3.name,"孙悟空");printf("%s,%d,%d \n",people3.name,people3.age,people3.height);//free(people3.name); //堆释放会对下面的strcpy(people4.name,people3.name);有影响/*如果结构体里面有指针,不能通过简单赋值完成操作,因为指向的是一样的*/struct man people4;people4.name = malloc(strlen(people3.name)+1);strcpy(people4.name,people3.name);people4.age = people3.age;people4.height = people3.height;printf("%s,%d,%d \n",people4.name,people4.age,people4.height);free(people3.name); //堆释放 free(people4.name); //堆释放 }chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out朴槿惠,40,170 王麻子,40,170 孙悟空,0,0 孙悟空,0,0




结构体指针 初步1

#include <stdio.h>#include <stdlib.h>#include <string.h>struct man{        char           *name;        unsigned char  age;        unsigned char  height;};int main(){        struct man   people1;        struct man  *people2 = &people1;        (*people2).name = malloc(10);        (*people2).age = 20;        (*people2).height = 170;        /*      上面的形式可以写成一下:*/        people2 -> name = malloc(10);        people2 -> age  = 20;        people2 -> height = 170;}编译通过chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outchunli@ubuntu:~/pointer$



结构体指针 初步2

#include <stdio.h>#include <stdlib.h>#include <string.h>struct man{        unsigned char  id;        char           name[20];        unsigned char  height;};int main(){        struct man   people[3] = {                                {1,"wang",181}, //wang属于常量                                {2,"li",182},                                {3,"zhang",189},                                };        /*      定义一个结构体指针      */        struct man  *people2 = &people[0];        printf("%d,%s,%d \n",people2->id,people2->name,people2->height);        /*      访问方式2,也可以方便for循环     */        printf("%d,%s,%d \n",people2[1].id,people2[1].name,people2[1].height);        people2++;//一次会移动一个结构体        printf("%d,%s,%d \n",people2->id,people2->name,people2->height);        /*        struct man  people1 = {1,"wang",181};        struct man  people2 = {2,"wang",181};        struct man  people3 = {3,"wang",181};        不要尝试用循环来遍历这样的数据,因为您不知道编译器是怎么安排的        最好放在同一个数组里面        */}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out1,wang,181 2,li,182 2,li,182




结构体的指针,初步3

#include <stdlib.h>#include <string.h>struct man{        unsigned char  id;        char           *name;        unsigned char  age;};int main(){        struct man   *sp = malloc(sizeof(struct man));        sp->id = 5;        sp->age = 10;        sp->name = malloc(10);        strcpy(sp->name,"zhang");        printf("%d,%s,%d \n",sp->id,sp->name,sp->age);        free(sp->name); // 一定先释放这个        free(sp);       //要不然sp-name永远找不到了        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out5,zhang,10








动态获取用户输入,不会浪费内存空间

#include <stdio.h>#include <stdlib.h>#include <string.h>struct test{char *name; //指针哦};struct man{unsigned char  id;char           *name;unsigned char  age;//struct test *p;  //有嵌套了一层,这是很难搞的};int main() {struct man   *sp = malloc(sizeof(struct man) * 10);memset(sp,0,sizeof(struct man) * 10);// 内存清零for(int i = 0;i<10;i++){sp[i].id = i;sp[i].age = i;char buf[999]={0};scanf("%s",buf);int len = strlen(buf);sp[i].name =malloc(len+1) ;sprintf(sp[i].name,"%s",buf);}for(int i = 0;i<10;i++){printf("%d,%s,%d \n",sp[i].id,sp[i].name,sp[i].age);}for(int i = 0;i<10;i++)//循环释放{free(sp[i].name);}free(sp);      //全部释放return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out1211111111111111111111111111111111111111111111111111111111111111111112222222222222222222222222222222222222222222222222222222222222222222aswsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvmmcsfdmcdsmc'nv vnvpmvpwvm[sdvfsdv dvdf  e fdf f0,12,0 1,1111111111111111111111111111111111111111111111111111111111111111111,1 2,2222222222222222222222222222222222222222222222222222222222222222222,2 3,a,3 4,s,4 5,wsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvm,5 6,mcsfdmcdsmc'nv,6 7,vnvpmvpwvm[sdv,7 8,fsdv,8 9,dvdf,9




形参是结构体的函数

#include <stdio.h>#include <stdlib.h>#include <string.h>struct man{        unsigned char  id;        char           *name;        unsigned char  age;};void fun1(struct man a_man){        printf("id = %d,age = %d,name = %s \n",a_man.id,a_man.age,a_man.name);        strcpy(a_man.name,"haha"); //会影响传过来的数据,因为指向的是同一块内存        a_man.id  = 99;            //而id就不会发生变化 }int main() {        //struct man   people1 = {0,"wang",100};        struct man   people1;        people1.id = 0;        people1.age = 10;        people1.name = malloc(10);        strcpy(people1.name,"wang");        fun1(people1);        printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outid = 0,age = 10,name = wang id = 0,age = 10,name = haha





结构体参数,地址与传值

chunli@ubuntu:~/pointer$ cat main.c #include <stdio.h>#include <stdlib.h>#include <string.h>struct man{unsigned char  id;char           name[100];unsigned char  age;};void fun1(struct man a_man)//传值过来{printf("id = %d,age = %d,name = %s \n",a_man.id,a_man.age,a_man.name);strcpy(a_man.name,"haha"); //无法修改a_man.id  = 99;            //无法修改}void fun2(struct man *sp)  //地址传过来      //void fun2(const struct man *sp)  //保护起来,防止修改{printf("id = %d,age = %d,name = %s \n",sp->id,sp->age,sp->name);strcpy(sp->name,"鲁智深"); //可以修改sp->id  = 66;             //可以修改}int main() {struct man   people1;people1.id = 0;people1.age = 10;strcpy(people1.name,"wang");fun1(people1);//fun1无法修改参数值printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);fun2(&people1);printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outid = 0,age = 10,name = wang id = 0,age = 10,name = wang id = 0,age = 10,name = wang id = 66,age = 10,name = 鲁智深




如何修改机构体内部的数组

#include <stdio.h>#include <stdlib.h>#include <string.h>struct str{char           buf[100];};void fun1(struct str s){strcpy(s.buf,"hello "); }void fun2(char s[]){strcpy(s,"hello"); }int main() {struct str s={"world!"}; ;fun1(s);//传结构体,相当于赋值过去了,不会改变变量 (会很消耗内存的性能)printf("%s \n",s.buf);char s1[100]="world!";fun2(s1);//数组会把地址传过去,会修改变量printf("%s \n",s1);return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outworld! hello








结构体函数 初始化结构体

#include <stdio.h>#include <stdlib.h>#include <string.h>struct str{        char           buf[100];};struct str getstr(){        struct str s;        strcpy(s.buf,"Hello World!");        return s;}char *getstr1(){        char buf[100];//在栈区        strcpy(buf,"Hello World!");        //return buf;//无法返回有效数据}int main() {        //char *tmp = getstr1();  非法执行        struct str tmp = getstr();        printf("%s \n",tmp.buf);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outHello World!




【指向结构体的指针】


返回结构体,消耗很大

#include <stdio.h>#include <stdlib.h>#include <string.h>struct str{        char           buf[100];};struct str getstr(){        struct str s;        strcpy(s.buf,"Hello World!");        return s;}char *getstr1(){        char buf[100];//在栈区        strcpy(buf,"Hello World!");        //return buf;//无法返回有效数据}int main(){        //char *tmp = getstr1();  非法执行        struct str tmp = getstr(); //内存拷贝,消耗很大        printf("%s \n",tmp.buf);        return 0;}





返回结构体指针,消耗很小

#include <stdio.h>#include <stdlib.h>#include <string.h>struct str{        char           buf[100];};struct str *getstr(){        struct str *s = malloc(sizeof(struct str));        printf("%p \n",s);        strcpy(s->buf,"Hello World!");        return s;//把指针返回去}int main() {        struct str *tmp = getstr(); //内存拷贝,消耗很大        printf("%p \n",tmp);        printf("%s \n",tmp->buf);        free(tmp);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out0x8cc010 0x8cc010 Hello World!





联合体初步1

#include <stdio.h>#include <stdlib.h>#include <string.h>union var{char  c;int i;short d;char *s;//很危险};struct str{char  c;int i;short d;};int main() {/*结构体与联合体元素地址区别*/union var v;//联合体元素公用用一个地址printf("%p \n" ,&(v.c));printf("%p \n" ,&(v.i));printf("%p \n" ,&(v.d));//小端对齐,高位放高位,低位放低位struct str s;//结构体,元素分别独立printf("%p \n" ,&(s.c));printf("%p \n" ,&(s.i));printf("%p \n" ,&(s.d));/*修改联合体元素*/printf("%ld \n",sizeof(v));v.c = 100;printf("%d \n",v.c); v.i = 1;printf("%d \n",v.c);return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out0x7ffc3f56e5d0 0x7ffc3f56e5d0 0x7ffc3f56e5d0 0x7ffc3f56e5e0 0x7ffc3f56e5e4 0x7ffc3f56e5e8 8 100 1




枚举

#include <stdio.h>#include <stdlib.h>#include <string.h>enum spectrum {red,yellow,green,blue,white,black};//申明一个枚举enum number {zero=10,one=9,two,three};//申明一个枚举void test(int i)                {printf("test \n");}void test1(int a,int b)         {printf("test1\n");}void test2(int a,int b,int c)   {printf("test2\n");}void *function_factory(enum number n){        if(n == zero)   return test;        if(n == one)    return test1;        if(n == two)    return test2;}void getcolor(enum spectrum color){        if(color == red)    printf("red \n");        if(color == yellow) printf("yellow \n");        if(color == green)  printf("green \n");        if(color == blue)   printf("blue \n");}int main() {        enum number b = one;        void *p = function_factory(b);          printf("%p ,%p  \n",p,test1);        enum spectrum  color = red;        getcolor(color);                            printf("%d,%d,%d \n",red,yellow,green);        printf("%d,%d,%d \n",zero,one,two);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out0x400594 ,0x400594  red 0,1,2 10,9,10



typedef 初步

#include <stdio.h>#include <stdlib.h>#include <string.h>typedef unsigned char BYTE;#define mybyte unsigned chartypedef unsigned int  UINT;//严格检查变量类型#define MAX 100 //简单替换,不做变量类型检查,没有分号struct student{        int id;        char name[100];};int main() {        BYTE b1 = 0xff;        printf("%x \n",b1);        UINT u1 = 0xFF00FF00;        printf("%x \n",u1);                //正常使用         struct student student1;        //typedef 来定义        typedef struct student STUDENT; //自定义 数据类型        STUDENT student2;        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outff ff00ff00




没有用typedef之前的代码,看着很晕

#include <stdio.h>#include <stdlib.h>#include <string.h>const char *func1(const char *str1,const char *str2){        char *p = malloc(strlen(str1) + strlen(str2) +1);        strcpy(p,str1);        strcat(p,str2);        return p;}const char *func2(const char *(*p)(const char *str1,const char *str2),const char *s1,const char *s2){        return p(s1,s2);}int main() {         const char *tmp1 = "Hello";        const char *tmp2 = "world!";        const char *s = func2(func1,tmp1,tmp2);        printf("%s  \n",s);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outHelloworld!



typedef优化 对比

#include <stdio.h>#include <stdlib.h>#include <string.h>//定义一个指向这种函数类型的指针typedef const char *(*FUNC1)(const char *str1,const char *str2);const char *func1(const char *str1,const char *str2){        char *p = malloc(strlen(str1) + strlen(str2) +1);        strcpy(p,str1);        strcat(p,str2);         return p;}const char *func2(FUNC1 p,const char *s1,const char *s2){        return p(s1,s2);}int main() {        const char *tmp1 = "Hello";        const char *tmp2 = "world!";        const char *s = func2(func1,tmp1,tmp2);        printf("%s  \n",s);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outHelloworld!




typedef深入1

#include <stdio.h>#include <stdlib.h>#include <string.h>//定义一个指向这种函数类型的指针 的数据类型typedef const char *(*FUNC1)(const char *str1,const char *str2);//这是函数的原始申明const char *func1(const char *str1,const char *str2){        char *p = malloc(strlen(str1) + strlen(str2) +1);        strcpy(p,str1);        strcat(p,str2);         return p;}const char *func2(FUNC1 p,const char *s1,const char *s2){        return p(s1,s2);}FUNC1 test(){FUNC1 tmp = func1;return tmp;}int main() {//定义10个FUNC1数据类型FUNC1 f[10];//定义一个数组10个元素,参数是const char *str1,const char *str2,返回值是 const char *const char *(*p[10])(const char *str1,const char *str2);         const char *tmp1 = "Hello ";        const char *tmp2 = "world!";        const char *s = func2(func1,tmp1,tmp2);        printf("%s  \n",s);        return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outHello world!



超级复杂的typedef

chunli@ubuntu:~/pointer$ cat main.c #include <stdio.h>#include <stdlib.h>#include <string.h>typedef unsigned char BYTE;typedef unsigned int UINT;#define MYBYTE unsigned char#define MAX 100//typedef 100 MYMAX;struct student{int ID;char name[MAX];};typedef struct student STUDENT;typedef const char *(*FUNC1)(const char *str1, const char *str2);const char *func1(const char *str1, const char *str2){char *p = malloc(strlen(str1) + strlen(str2) + 1);strcpy(p, str1);strcat(p, str2);return p;}/*const char *(*)(const char *str1, const char *str2) test(){FUNC1 tmp = func1;return tmp;}*/const char *func2(const char *(*p[])(const char *str1, const char *str2), const char *s1, const char *s2){return (p[0])(s1, s2);}int main(){FUNC1 f[10];//const char *tmp1 = "hello ";const char *tmp2 = "world";f[0] = func1;const char *s = func2(f, tmp1, tmp2);printf("s = %s\n", s);BYTE b;b = 0x12;UINT i;i = 0xffff;STUDENT st;return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outs = hello worldchunli@ubuntu:~/pointer$




【复习================================】


联合体的指针,很危险

#include <stdio.h>#include <stdlib.h>#include <string.h>union var{char  c;int i;short d;char *s;//很危险}; int main() {union var v;v.s = (char *)malloc(100);v.c = 1;free(v.s);//致命错误! return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.outSegmentation fault (core dumped)



typedef 特别高级的用法

chunli@ubuntu:~/pointer$ cat main.c #include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct student ST;struct  student{char  name[200];int id;};typedef const char *(*FUNC1)(const char *str1,const char *str2) ;const char *funcl(const char *str1,const char *str2){printf("%s,%s \n",str1,str2);return NULL;}const char *func2(FUNC1 p, const char *str1,const char *str2){return p(str1,str2);}int main() {ST student1;strcpy(student1.name,"奥巴马");student1.id = 1;printf("%d,%s \n",student1.id,student1.name);return 0;}chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out1,奥巴马




不使用typedef

C 结构体 联合体 typedef



使用typedef

C 结构体 联合体 typedef

本文出自 “李春利” 博客,请务必保留此出处http://990487026.blog.51cto.com/10133282/1782752