欢迎光临散文网 会员登陆 & 注册

C语言结构、联合、枚举

2023-01-31 09:49 作者:虚云幻仙  | 我要投稿

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <ctype.h>


void func1(void);

void func2(void);

void manybook(void);

char* s_gets(char* s, int limit);

void generate1(void);

void get_ins_info(struct insurance* sp);

void get_ins_info2(struct insurance s);

void booksave(void);

void seat_reserve(void);

void show_empty_num(struct seat* sp, int size);

void show_empty_list(struct seat* sp, int size);

void show_alphabetical_list(struct seat* sp, int size);

void assign_seat(struct seat* sp, int size);

void delete_seat(struct seat* sp, int size);

void other1(void);

void func1(void)

{

     struct month { char name[20]; char abbre[4]; int days; int num; }; //structure结构,可将多种类型组成一个整体。

     // 格式:struct 结构标识符 {字段1类型(field字段/member成员,结构中包含的数据的类型) 字段1标识符;字段2类型 字段2标识符...} 变量名;

     //不写变量名只写标识符则为只声明结构类型,不创建变量,声明结构类型不会产生内存块。而写变量名会创建该结构,不需要多次创建该结构可以省略标识符

     struct month January = { "January","jan",31,1 }; // 创建结构变量时格式: struct 结构标识符 变量名 ,定义变量时可以使用{value1,value2...}初始化结构,需按照结构声明的字段顺序,如果不初始化则该内存块仍然保留之前的垃圾值

     printf("%s has %d days", January.name, January.days); //结构变量通过 . 成员运算符访问结构的成员

     struct month year[12] = { January,[1] = {"February",.num = 2} }; //声明结构数组,和普通类型的数组方法一样,只写了1月和2月,剩下的部分会初始化为0,结构变量的初始化中通过.num的形式(初始化器)给2月的num成员初始化为2,没有显式初始化的abbre和days会初始化为0

     strcpy(year[1].abbre, "feb"); //给结构的成员单独赋值,字符数组需要strcpy/strncpy完成赋值,而对整个结构赋值时不需要对每个字符数组字段使用strcpy

     year[1].days = 28;

     year[2] = (struct month){ "March","mar",31,3 }; //复合字面量,格式(struct 结构标识符){每个成员/字段的值}

     // 省略数组剩余月份赋值过程

     char user_input[20] = "";

     int total = 0;

     puts("输入月份名:");

     scanf("%19s", user_input);

     for (int i = 11; i >= 0; i--)

     {

         if (strcmp(user_input,year[i].name)==0)

         {

             for (int j = 0; j <= i; j++)

             {

                 total += year[j].days;

             }

             printf("当年直到该月一共有%d天\n", total);

             break;

         }

     }

     if (total==0)

     {

         puts("月份名错误");

     }

}

void func2(void)

{

     extern struct month

     {

         char name[20];

         char abbre[4];

         int days;

         int num;

     } months[]; //引用定义好的结构数组,数组大小应省略,但结构类型的字段内容不能省略,C将结构类型的所有字段完全相同的结构视为同一个结构类型,不论结构类型标识符

     printf("输入年:");

     int y, d;

     char m[20]="";

     int m_index;

     if (scanf("%d", &y)==1)

     {

         if (y%4==0)

         {

             months[1].days = 29; //处理闰年

         }

         printf("输入月:");

         if (scanf("%19s", m)==1) //可以输入英文全称、缩写、数字

         {

             if ((m_index = (int)strtol(m, NULL, 10))!=0) //strtol()转换失败/字符串开头没有读取到数字返回0

             {

                 if (m_index<1||m_index>12) //检测数字有效性

                 {

                     m_index = 12; //设置为无用值

                 }

                 else

                 {

                     m_index--; //月份号比数组索引多1

                 }

             }

             else    //m_index 在if中判断为0

             {

                 for (; m_index < 12; m_index++)

                 {

                     if (strcmp(months[m_index].name, m) == 0 || strcmp(months[m_index].abbre, m) == 0) //比较英文,如果数组元素都不匹配m_index的值变为12和上面的无用值一致

                     break;

                 }

             }

             if (m_index<12) //小于12则一定为0-11中的一个有效数

             {

                 printf("输入日:");

                 if (scanf("%d", &d)==1&&d>0&&d<=months[m_index].days) //检测日的有效性

                 {

                     int total = d;

                     for ( int i = 0; i < m_index; i++)

                     {

                         total += months[i].days;

                     }

                     printf("%d年%s月%d日是这一年的第%d天\n", y, m, d, total);

                     return;

                 }

             }

         }

     }

     puts("输入有误");

}

void manybook(void)

{

     struct book { //在函数中声明的结构类型具有块作用域,在函数外声明具有文件作用域

         char title[40];

         char author[40];

         float value;

     } library[100];

     int count = 0;

     int index;

     printf("Please enter the book title.\nPress [enter] at the start of a line to stop.\n");

     while (s_gets(library[count].title, 40)!=NULL&&library[count].title[0]!='\0') //得到标题

     {

         puts("Now enter the author.");

         s_gets(library[count].author, 40);

         puts("Now enter the value.");

         scanf("%f", &library[count++].value); //完成一个结构的赋值,count++

         while (getchar()!='\n')

             continue; //清空行

         if (count < 100)

             puts("Enter the next title.");

         else

             break;

     }

     if (count>0)

     {

         struct book** parr = (struct book**)malloc(count * sizeof(struct book*)); //动态分配包含count个指向book结构的指针元素的数组,*parr[]转换为**parr

         //函数返回void*,需要强转成parr的类型,malloc的参数是字节的数量,与类型无关,返回的是内存块的首地址,需要转换成什么类型就转换成什么类型,应转换成和parr同类型,而不是struct book*

         puts("Here is the list of your books:");

         for ( index = 0; index < count; index++)

         {

             printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);

             parr[index] = library + index; //指针数组的指针逐一指向结构数组的元素

         }

         struct book* temp;

         int complete;

         for ( index = 0; index < count; index++)

         {

             complete = 1;

             for (int j = count-1; j >index; j--)

             {

                 if (strcmp((*parr[j - 1]).title,parr[j]->title)>0) //通过指针访问结构变量的两种写法,library[j]是结构,parr[j]=&library[j]是指针/地址,*parr[j]是结构,(*parr[j]).title结构调用字段,解引用*优先级低于. 成员运算符需要括起来,另一种常用写法parr[j]->title和(*parr[j]).title等价,结构地址->结构字段,(*结构地址).结构字段,->间接成员运算符

                 {

                     temp = parr[j];

                     parr[j] = parr[j - 1];

                     parr[j - 1] = temp;

                     complete = 0;

                 }

             }

             if (complete)

             break;

         }

         for (index = 0; index < count; index++)

         {

             printf("%s by %s: $%.2f\n", parr[index]->title, parr[index]->author, parr[index]->value);

         }

         for ( index = 0; index < count; index++)

         {

             complete = 1;

             for (int j = count-1; j >index; j--)

             {

                 if (parr[j-1]->value>parr[j]->value)

                 {

                     temp = parr[j];

                     parr[j] = parr[j - 1];

                     parr[j - 1] = temp;

                     complete = 0;

                 }

             }

             if (complete)

                 break;

         }

         for (index = 0; index < count; index++)

         {

             printf("%s by %s: $%.2f\n", parr[index]->title, parr[index]->author, parr[index]->value);

         }

         free(parr); //动态生成的内存最好在创建时就附上释放的代码避免遗忘

     }

     else

     {

         puts("No books? Too bad.");

     }

}

char* s_gets(char* s, int limit)

{

     char* p1 = fgets(s, limit, stdin);

     if (p1)

     {

         char* p2 = strchr(s, '\n');

         if (p2)

         *p2 = '\0';

         else

             while (getchar() != '\n')

                 continue;

     }

     return p1;

}

struct insurance { //结构储存保险的编号和人名

     unsigned long num;

     struct fullname { // 结构中使用结构,fullname结构类型字段包含名、中间名和姓,字段的标识符为name,如果之前已经声明了fullname结构,则简写为struct fullname name; 如果该结构只在这里使用,可不写fullname结构类型标识符

         char first[20];

         char mid[20];

         char last[20];

     } name;

};

void generate1(void)

{

    struct insurance customers[5] = {

         {302038923,{"Dribble","Mac","Flossie"}},

         {302038543,{"Abel","Ken","Smith"}},

         {302345922,{"Caleb","","Jones"}},

         {302876924,{"Ford",.last = "williams"}}, // 跳过mid给last赋值

         {305678926,{"Eddie","Que","Brown"}},

     }; //结构数组,每个元素内又有一个结构需要再加一层大括号

     get_ins_info(customers); //第一个元素的地址

     get_ins_info2(customers[1]); //第二个元素的值

}

void get_ins_info(struct insurance* sp)

{

     printf("%s , %s ", sp->name.first,sp->name.last); // 指针->结构字段标识符.char字段标识符,如果声明insurance结构时省略了内部结构字段的标识符name,则insurance类型变量在使用时直接通过.即可访问内部结构的字段,写作sp->first

     if (sp->name.mid[0])

     {

         printf("%c. ", sp->name.mid[0]);

     }

     printf("--%lu\n", sp->num);

}

void get_ins_info2(struct insurance s) //将结构作为值接收,形参s初始化为函数调用时实参/值的备份

{

     struct insurance s2 = s; //结构可以赋值,结构名不是地址(不同于数组)

     printf("%s , %s ", s2.name.first, s2.name.last);

     if (s2.name.mid[0])

     {

         printf("%c. ", s2.name.mid[0]);

     }

     printf("--%lu\n", s2.num);

     // 这也意味着,更改s或s2的值不会影响主调函数的变量

}

typedef struct { struct { char first[20]; char last[20]; }; double score[3]; double average; } STUDENT; //使用typedef取别名,将整个嵌套结构取别名为student,好处是定义结构变量时不需要写struct,坏处是不能显式表明该类型为结构,所以建议用大写来表示该类型为复杂的类型

//由于使用typedef,结构的标识符就没用了省略,内部结构没有声明字段名,所以直接.调用内部的字段,如果函数的形参使用了typedef声明的别名,需要将typedef声明放在函数原型之前才能生效

void get_student_info(STUDENT* sp) //STUDENT是某个结构的类型,所以sp是结构的指针

{

    printf("%s %s : %.2f %.2f %.2f avg:%.2f\n", sp->first, sp->last, sp->score[0], sp->score[1], sp->score[2], sp->average); //匿名内部结构的first/last通过外部结构直接.first调用

}

#define MAXTITL 40 //define预处理只对该行以下的MAXTITL生效

#define MAXAUTL 40

#define MAXBKS 10

struct book

{

     char title[MAXTITL];

     char author[MAXAUTL];

     float value;

};

void booksave(void)

{

     struct book library[MAXBKS]; // 自动存储类别的对象被储存在栈中,如果结构数组大小很大,会造成栈溢出,可以使用编译器选项设置栈大小为10000或创建静态数组(包括静态块作用域),编译器不会将静态数组放在栈中

     struct book *ptra[MAXBKS], *temp;

     int count = 0;

     int index, filecount;

     char s[2];

     FILE* pbooks;

     int size = sizeof(struct book); //将book结构的尺寸记录

     if ((pbooks=fopen("data01.txt","rb"))==NULL)

     {

         fputs("Can't open data01.txt file\n", stderr);

         exit(1);

     }

     while (count<MAXBKS&&fread(library+count,size,1,pbooks)==1) //将结构在内存中的值原样保存到二进制文件中,读取时按结构的尺寸逐个结构读取,fread()返回读取到的数据块

     {

         if (count==0)

         {

             puts("Current contents of data01.txt:");

         }

         printf("No.%d %s by %s: $%.2f\n", count, library[count].title, library[count].author, library[count].value);

         count++; //count记录图书列表中图书的总数

     }

     for (int i = 0; i < MAXBKS; i++)

     {

         ptra[i] = library + i; // 将指针数组和结构数组逐一对应,指针数组的元素是指向结构的指针,结构数组的元素是结构

     }

     while (puts("a)add new book\tu)update exist book\td)delete exist book\tq)quit"),s_gets(s,2)!=NULL&&s[0]!='q') //增删改查

     {

         switch (s[0])

         {

             case 'a':

                 if (count>=MAXBKS)

                 {

                     puts("The data01.txt file is full. You can delete some books or update.");

                 }

                 else

                 {

                     puts("Please add new book titles.\nPress [enter] at the start of a line to stop.");

                     while (s_gets(ptra[count]->title,MAXTITL)!=NULL&& ptra[count]->title[0]!='\0') //使用指针数组添加book

                     {

                         puts("Now enter the author.");

                         s_gets(ptra[count]->author, MAXAUTL);

                         puts("Now enter the value.");

                         scanf("%f", &ptra[count++]->value); //当前元素所有信息录完,递增count

                         while (getchar()!='\n')

                         {

                             continue;

                         }

                         if (count<MAXBKS)

                         {

                             puts("Enter the next title.");

                         }

                         else

                         {

                             break;

                         }

                     }

                 }

                 break;

             case 'u':

                 if (count<=0)

                 {

                     puts("There are not books in the file.");

                     continue;

                 }

                 else

                 {

                     printf("Which book do you want to update(0-%d,other to quit)?", count-1); //0到count-1

                     while (s_gets(s,2)!=NULL)

                     {

                         index = s[0] - '0'; //ASCII字符集中,数字字符减'0'字符等于数字的值

                         if (index>=0&&index<count)

                         {

                             printf("No.%d %s by %s: $%.2f\nt)title\ta)author\tv)value\n", index, ptra[index]->title, ptra[index]->author, ptra[index]->value);

                             if (s_gets(s, 2) != NULL && s[0] != '\0' && strchr("tav", s[0]) != NULL) //strchr函数参数2是\0时会返回参数1字符串的末尾\0的位置,不为null

                             {

                                 printf("new content:");

                                 switch (s[0])

                                 {

                                     case 't':

                                         s_gets(ptra[index]->title, MAXTITL);

                                         break;

                                     case 'a':

                                         s_gets(ptra[index]->author, MAXAUTL);

                                         break;

                                     case 'v':

                                         scanf("%f", &ptra[index]->value);

                                         while (getchar() != '\n')

                                             continue;

                                 }

                                 printf("No.%d %s by %s: $%.2f\nt)title\ta)author\tv)value\n", index, ptra[index]->title, ptra[index]->author, ptra[index]->value);

                             }

                         }

                         else

                         {

                             break;

                         }

                         printf("Which book do you want to update(0-%d)?", count - 1);

                     }

                 }

                 break; //每个case的break

             case 'd':

                 if (count <= 0)

                 {

                     puts("There are not books in the file.");

                     continue;

                 }

                 else

                 {

                     printf("Which book do you want to delete(0-%d)?", count - 1);

                     if (s_gets(s,2)!=NULL&&(index=s[0]-'0')>=0&&index<count)

                     {

                         printf("No.%d %s by %s: $%.2f\n", index, ptra[index]->title, ptra[index]->author, ptra[index]->value);

                         printf("Delete(y/n)?");

                         if (s_gets(s, 2) != NULL && tolower(s[0]) == 'y')

                         {

                             if (index<MAXBKS-1)

                             {

                                 temp = ptra[index];

                                 memmove(ptra + index, ptra + index + 1, (MAXBKS - 1 - index) * sizeof(struct book*)); //操作指针数组,将指向要删除的book的指针元素后面的元素前移,使用memmove复制整块数据对象,将指向要删除的book的地址(结构数组中该book元素的地址)交换到指针数组的最后一位元素上,这一步操作并没有清除数据

                                 ptra[MAXBKS - 1] = temp;

                             }

                             count--; //记录总数的count递减,因为移动了指针数组的部分元素,前count个元素依然是当前的图书,而要删除的book的地址被移动到count范围外,不能读取相当于删除,这也完成了删除book使后面的book前移的操作,而如果要删除的是索引9即指针数组的最后一个指针,则只需要递减count将该book排除,经过删除操作后,指针数组的元素顺序和结构数组的元素顺序不再相同,但依旧保持一对一的关系 

                             puts("Delete success.");

                         }

                     }

                 }

                 break;

             default:

                 continue;

         }

         if (count>0)

         {

             puts("Here is the list of your books:");

             for (index = 0; index < count; index++)

             {

                 printf("No.%d %s by %s: $%.2f\n", index, ptra[index]->title, ptra[index]->author, ptra[index]->value); //顺序以指针数组为准

             }

         }

         else

         {

             puts("The list of your books is empty now.");

         }

     }

     fclose(pbooks);

     if (pbooks = fopen("data01.txt", "wb")) //清空文件

     {

         for ( index = 0; index < count; index++)

         {

             fwrite(ptra[index], size, 1, pbooks); //只保存指针数组中前count个元素指向的结构

         }

         fclose(pbooks);

     }

     if (count<=0)

     {

         puts("No books? Too bad.\n");

     }

     puts("Bye.\n");

}

struct seat {

     int num;

     _Bool reserved;

     char first[20];

     char last[20];

};

#define SEATSIZE 12

void seat_reserve(void)

{

     struct seat seats[SEATSIZE] = {

         {1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12} //初始化座位编号,reserved字段预定状态默认初始化为0

     };

     puts("To choose a function, enter its letter label:\na)Show number of empty seats\tb)Show list of empty seats\nc)Show alphabetical list of seats\td)Assign a customer to a seat assignment\ne)Delete a seat assignment\tf)Quit");

     char ch;

     typedef void (*func_ptr)(struct seat*, int); //逐步分析,void func()为函数,无返回,void* func()为返回指向void指针的函数(因为括号优先级高于解引用,func和()结合成为函数,圆括号(2+3)和方括号[i]优先级相同), void (*func)()为函数指针,因为*先和func结合,使func成为指针,然后将*func看成一个整体和()结合成为函数,也就是说*func是函数,func是指针,然后void声明该函数为void类型,函数的类型+函数的形参列表合称函数签名,所以func是指向函数的指针,该函数为void类型有两个形参

    //typedef 类型 别名, 对于函数,typedef 函数签名 别名,(*func_ptr)以外的部分为函数签名,*func_ptr为函数,func_ptr为函数指针类型的别名

     //声明函数指针的方法为,先写出函数原型,void func(),再将函数名替换为 (*标识符) 的形式,标识符代表的就是函数指针

     func_ptr func_ptrs[5] = { show_empty_num,show_empty_list ,show_alphabetical_list ,assign_seat ,delete_seat }; //声明包含五个函数指针元素的数组,函数名为函数的地址,加括号为调用

     //如果不使用typedef,声明指针数组的格式为:void (*func[5])() ,func先和[5]结合成为数组,再和*结合成为存放指针的数组,再()存放函数指针,再void。如果写成void (*func)[5](),因为括号()和[]优先级相同,根据结合律从左到右,func和*成为指针,和[5]成为指向5个元素数组的指针,这时(*func)[5]整体为一个数组,数组外的部分都是数组元素的定义,所以和()结合使元素成为函数,再void,但C不允许函数数组,这样的声明时非法的,只能声明函数指针的数组

     while ((ch=tolower(getchar()))!='f')

     {

         if (ch != '\n')

             while (getchar() != '\n')

                 continue;

         if (strchr("abcde", ch) && ch != '\0')

             (*func_ptrs[ch - 'a'])(seats, SEATSIZE); //func_ptrs为函数指针的数组,func_ptrs[0]为函数指针,(*func_ptrs[0])为函数,后面加(参数)来调用,因为*优先级低于()函数调用所以要括起来,C允许(*函数指针)(参数)的形式,也允许函数指针(参数)的形式(不推荐)

         //a-a=0 e-a=4,对应指针数组的五个函数

         puts("To choose a function, enter its letter label:\na)Show number of empty seats\tb)Show list of empty seats\nc)Show alphabetical list of seats\td)Assign a customer to a seat assignment\ne)Delete a seat assignment\tf)Quit");

     }

}

void show_empty_num(struct seat* sp, int size)

{

     int count = 0;

     for (int i = 0; i < size; i++)

     {

         if (sp[i].reserved)

         continue;

         printf("%d\t", sp[i].num);

         count++;

     }

     if (count)

         putchar('\n');

     else

         puts("These are not empty seats now.");

}

void show_empty_list(struct seat* sp, int size)

{

     for (int i = 0; i < size; i++)

     {

         if (sp[i].reserved)

             continue;

         printf("seat number:%d  status:not reserved  customer information:none\n", sp[i].num); //sp是指针,sp[i]是结构,*sp是结构,sp+i是地址,所以也可以写成(sp+i)->num

     }

    

}

void show_alphabetical_list(struct seat* sp, int size)

{

     struct seat** temparr = (struct seat**)malloc(size*sizeof(struct seat*)); //动态分配内存

     for (int i = 0; i < size; i++)

     {

         temparr[i] = sp + i;

     }

     int complete;

     for (int i = size-1; i >0; i--)

     {

         complete = 1;

         for (int j = 0; j < i; j++)

         {

             if (temparr[j]->first[0])

             {

                 if (temparr[j + 1]->first[0]&& strcmp(temparr[j]->first, temparr[j + 1]->first) > 0)

                 {

                     sp = temparr[j]; //sp传参给temparr之后就没用了,当做交换用临时变量

                     temparr[j] = temparr[j + 1];

                     temparr[j + 1] = sp;

                     complete = 0;

                 }

             }

             else if (temparr[j + 1]->first[0])

             {

                 sp = temparr[j];

                 temparr[j] = temparr[j + 1];

                 temparr[j + 1] = sp;

                 complete = 0;

             }

         }

         if (complete)

             break;

     }

     for (int i = 0; i < size; i++)

     {

         printf("seat number:%d  status:%s  customer information:%s %s\n", temparr[i]->num, temparr[i]->reserved?"reserved" : "not reserved", temparr[i]->first, temparr[i]->last); //temparr是指向指针的指针,temparr[i]是指针,(*temparr[i])是结构,等价于temparr[i][0]

     }

     free(temparr);

}

void assign_seat(struct seat* sp, int size)

{

     printf("Enter the number of seat to assign(1-%d other to quit):", size);

     int a;

     char ch;

     while (scanf("%d",&a)==1&&a>0&&a<=size)

     {

         while (getchar() != '\n')

             continue;

         if (sp[a-1].reserved)

         {

             puts("The seat have been reserved. Try another:");

             continue;

         }

         printf("Enter the first name and last name:");

         scanf("%19s%19s", sp[a - 1].first, sp[a - 1].last);

         while (getchar() != '\n')

             continue;

         printf("Sure(y/n)?");

         if ((ch=tolower(getchar()))=='y')

         {

             sp[a - 1].reserved = 1;

             puts("Success.");

         }

         if(ch!='\n')

         while (getchar() != '\n')

              continue;

         printf("Enter the number of seat to assign(1-%d other to quit):", size);

     }

     while (getchar() != '\n')

         continue;

}

void delete_seat(struct seat* sp, int size)

{

     printf("Enter the number of seat to delete(1-%d other to quit):", size);

     int a;

     char ch;

     while (scanf("%d", &a) == 1 && a > 0 && a <= size)

     {

         while (getchar() != '\n')

             continue;

         if (sp[a - 1].reserved)

         {

             printf("seat number:%d  status:%s  customer information:%s %s\n", sp[a - 1].num, sp[a - 1].reserved ? "reserved" : "not reserved", sp[a - 1].first, sp[a - 1].last);

             printf("Sure(y/n)?");

             if ((ch = tolower(getchar())) == 'y')

             {

                 sp[a - 1].reserved = 0;

                 sp[a - 1].first[0] = '\0';

                 sp[a - 1].last[0] = '\0';

                 puts("Success.");

             }

             if (ch != '\n')

                 while (getchar() != '\n')

                     continue;

             printf("Enter the number of seat to delete(1-%d other to quit):", size);

         }

         else

         {

             puts("The seat is empty. Try another:");

             continue;

         }

     }

     while (getchar() != '\n')

         continue;

}

void other1(void)

{

     union MyUnion // 联合union,是一种数据类型,创建一个空间储存字段,大小为字段中最大的字段的大小,同一时间只能存储其中一个字段

     {

         int i;

         float f;

         char ch;

         double d;

         struct { short s1; short s2; };

     } u = {1.2}; //联合初始化默认初始化为第一个字段的类型,1.2发生截断,如果要指定初始化为d字段,使用{.d=1.2}

     u.s1 = 20; //匿名结构直接调用,对联合的其他字段赋值会覆盖之前的字段值,同时间只能存储一个字段,即便该字段默认大小远小于联合的大小

     struct { int uniontype; union MyUnion value} su = { 1,{20} }; //用一个标识记录当前联合中存储的类型,如type=1说明value.i有效,这样做使得数据块的大小一致,存储和读取时通过type访问联合正确的成员

     struct ss {

         int status;

         union {

             char c;

             short s;

         }; // 匿名联合,可通过结构变量.c直接访问联合成员

     };

     struct flexible //在结构中使用伸缩型数组成员

     {

         int size;

         double arr[]; //最后一个成员声明为一个不写大小的数组

     }; //这个结构类型的大小为伸缩型数组成员以外所有字段大小的和,这里是1个int的大小,也就是说这时结构的.arr并不存在

     struct flexible* sp = malloc(sizeof(struct flexible) + 5*sizeof(double)); //这种结构需要配合动态分配内存,在结构的大小之外增加数组所需的大小,这里设定数组有5个double元素

     sp->size = 5; //在结构中记录数组的尺寸

     for (int i = 0; i < sp->size; i++)

     {

        sp->arr[i] = i * 1.0; //对每个元素赋值

     }

     free(sp); //因为结构实际上不包含伸缩型数组成员,所以使用结构赋值时只会拷贝除数组以外的部分

     enum MyEnum //枚举类型,enumerated type,声明符号名称来表示整形常量,enum实际类型为int

     {

         ZERO,ONE,THREE=3,FOUR,EIGHT=8,NINE //这里声明的ZERO的值为0,接着的ONE的值为1,枚举默认从0开始,通过符号名称=来对特定符号赋值,之后的符号顺着上一个的值递增

     };

     enum MyEnum i; //声明枚举变量,实际类型为int,可以是任意int的值

     char st[NINE]; //可以使用枚举常量定义数组大小,和#define NINE 9作用类似

     //补充: *解引用&取址运算符优先级低于.成员运算符->间接成员运算符,所以ptr->xx改为(*ptr).xx,而*ptr->ptr2->struct3.memberptr会解引用memberptr,&ptr->member会取址member,三种括号(无论用法)的优先级和.->同级(同为最高级),所以ptr->func()根据结合律从左往右先找到ptr指向的结构的func成员再作为函数调用,funcs[23]()同样从左往右

}


C语言结构、联合、枚举的评论 (共 条)

分享到微博请遵守国家法律