结构体公用体枚举
Posted lemongirl
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了结构体公用体枚举相关的知识,希望对你有一定的参考价值。
一.结构体类型
1.结构体变量的定义与使用
? 定义结构体变量的方式
? 先申明结构体类型再定义变量名
struct stu //stu:结构体类型名
{
成员列表
};
struct stu Lucy; //Lucy:结构体变量名
? 在声明类型的同时定义变量
struct stu //stu:结构体类型名
{
成员列表
}Lucy,Bob; //Lucy、Bob:结构体变量名
? 直接定义结构体类型变量(无类型名)
struct //无类型名
{
成员列表
}Lucy、Bob; //Lucy、Bob:结构体变量名
? 结构体类型名:指定了一个结构体类型,它相当于一个模型,但其中并无具体数据,系统对之也不分配实际的内存单元。
? 结构体变量名:实际分配空间——为了能在结构体中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据。
? 比较推荐的写法
typedef struct stu
{
成员列表
}STU; //使用typedef重新定义一个结构体类型名
STU Lucy,Bob; //使用STU去定义相应的对象
类型与变量分开定义,当一个结构体类型有多个文件需要使用时,可以将类型定义放在放在一个.h文件中,需要使用的文件包含相应的头文件即可。
? 注意事项:
1.结构体变量成员必须单独使用:结构体变量名.成员名
例如:Lucy.num = 101;
scanf("%c",&Lucy.sex);
printf("%s\n",Lucy.name);
2.具有相同类型的结构体变量可以相互赋值,多用于结构体成员整体操作(排序等)
例如:Bob = Lucy;
3.结构体可以在定义的时候进行初始化
例如:STU Lucy = {12,"hello",‘m‘};
4.允许嵌套定义结构体变量,成员引用多级引用
例如:Lucy.birthday.month = 12;
#include <stdio.h> typedef struct stu { int num; char name[10]; char sex; }STU; int main(int argc,char *argv[]) { STU boy1,boy2,girl = {15,"lucy",‘w‘}; printf("input boy2 num name sex:"); scanf("%d %s %c",&boy2.num,boy2.name,&boy2.sex); boy1 = boy2; printf("boy1.num = %d,boy1.name = %s,boy1.sex = %c\n",boy1.num,boy1.name,boy1.sex); printf("boy2.num = %d,boy2.name = %s,boy2.sex = %c\n",boy2.num,boy2.name,boy2.sex); printf("girl.num = %d,girl.name = %s,girl.sex = %c\n",girl.num,girl.name,girl.sex); return 0; }
2.结构体数组
? 结构体数组中每个数组元素都是一个结构体类型的数据
? 直接定义结构体数组
struct student
{
int num;
char name[10];
int age;
}edu[2];
? 结构体数组的引用
edu[0].num = 10;
strcpy(edu[0].name,"Lucy");
edu[0].age = 24;
//定义一个结构体数组 #include <stdio.h> typedef struct stu { int num; char name[10]; float score; }STU; int main(int argc,char *argv[]) { STU msg[3] = { {15,"lucy",88.5}, {16,"peter",91.5}, {101,"bob",62.5} }; int i; float aver,sum = 0; for(i = 0;i < 3;i++) { sum = sum + msg[i].score; } aver = sum/3; printf("axer = %f\n",aver); return 0; }
3.结构体指针
指向结构体变量首地址的指针,通过结构体指针即可访问该结构体变量
? 结构体指针变量定义:
struct 结构体名 *结构体指针变量 例如:struct student *p = &Lucy;
? 利用结构体指针变量访问结构体变量的各个成员
1.Lucy.num = 101;
2.(*p).num = 101;
3.p->num = 101; //"->"称为指向运算符
4.(&Lucy)->num = 101;
? 结构体指针主要用于结构体变量传参以及链表中
//利用结构体指针变量访问结构体变量的成员 #include <stdio.h> typedef struct stu { int num; char name[10]; float score; }STU; int main(int argc,char *argv[]) { STU Lucy = {100,"Lucy",80}; STU *p = &Lucy; printf("num = %d,num = %d\n",Lucy.num,p->num); printf("name = %s,name = %s\n",Lucy.name,(*p).name); printf("score = %.2f,score = %.2f\n",Lucy.score,(&Lucy)->score); return 0; }
4.结构体的内存分配
? 结构体对其,默认对其原则
1.数据类型对其值:
char型数据自身对其值为1,short为2,int、float为4,double(windows:8,Linux:4)
解释:
char变量只要有一个空余的字节即可存放
short要求首地址能被2整除
int、float、double同理
2.结构体的对其值:
其成员中自身对其值最大的那个值
解释:
结构体最终对其按照数据成员中最长的类型的整数倍
3.分析以下结构体所占空间大小
struct stu1 { char a; int b; short c; }STU1; //sizeof(STU1) = 12 struct stu2 { int b; char a; short c; }STU2; //sizeof(STU2) = 8 struct stu3 { char a; int b; }STU3; //sizeof(STU3) = 8
? 指定对其原则:使用#pragma pack改变默认对其原则
1.格式:#pragma pack(value) //value:指定对其值
? value只能是:1 2 4 8
? 指定类型值与数据类型对其值相比取较小值
例如:设为1:则short、int、float等均为1
设为2:则char仍为1,short为2,int变为2
2.分析一下结构体所占空间大小
#pragma pack (1) struct stu { char a; int b; short c; }STU; //sizeof(STU) = 7 #pragma pack (8) struct stu1 { char a; int b; short c; }STU; //sizeof(STU) = 12
5.位段的使用
? 位段的定义
struct packed_data
{
unsigned int a:2;
unsigned int b:6;
unsigned int c:4;
unsigned int d:4;
unsigned int i;
}data; //其中a,b,c,d分别占2位,6位,4位,4位,i为整型占字节(32位)
? 位段的使用
data.a = 2; //赋值时,不要超出位段定义的范围;如果位段成员a定义为2位,最大值为3,即(11)2,所以data a = 5,就会取5的低两位进行赋值
? 位段定义的重要说明
1.位段成员的类型必须指定为整型或字符型,即char、short、int、long型,不能是浮点型,也不能定义位段数组。
2.一个位段必须存放在一个存储单元中,不能跨两个单元,即第一个单元空间不能容纳下一个位段,则该空间不用,而从下一个单元起存放该位段
3.位段的长度不能大于存储单元的长度。
4.如果一个位段要从下一个存储单元开始,可以定义:
unsigned a:1;
unsigned b:2;
unsigned :0; //长度为0的位段,其作用是使下一个位段从下一个存储单元开始存放,将a、b存储在一个存储单元中,c另存在下一个单元
unsignde c:3;(另一个位段)
5.可以定义无意义的位段,如:
unsigned int a: 1;
unsigned int : 2;
unsigned int b: 3;
#include <stdio.h> typedef struct { unsigned int a:1; unsigned int b:2; unsigned int c:3; }M; //sizeof(M) = 4 typedef struct b { unsigned int a:1; unsigned int b:2; unsigned int c:32; }B; //sizeof(B) = 8 int main(int argc,char *argv[]) { M k; k.a = 1; printf("k.a = %d\n",k.a); //k.a = 1 k.b = 1; printf("k.b = %d\n",k.b); //k.b = 1 // k.b = 4; // printf("k.b = %d\n",k.b); //k.b = 0 k.c = 4; printf("k.c = %d\n",k.c); //k.c = 4 // printf("k.a_len = %d\n",sizeof(k.a)); //错误,sizeof()是测字节长度,k.a是位段 printf("M_len = %d\n",sizeof(M)); //M = 4 printf("B_len = %d\n",sizeof(B)); //B = 12 return 0; }
二.共用体类型(联合体类型)
? 共用体的定义
与结构体非常类似,有三种方式,推荐使用以下这种方式
typedef union data
{
short int num; //短整型2字节
char sex; //字符型1字节
float score; //浮点型4字节
}DATA;
DATA a,b;
? 共用体的引用
a.num(引用共用体变量中的整型变量num)
a.sex(引用共用体变量中的字符型变量sex)
a.score(引用共用体变量中的实型变量score)
? 共用体的特点
? 同一内存段可以用来存放几种不同类型的成员,但每一瞬时只能存放其中一个成员,只有一种起作用,而不是同时存放几个。也就是说,在共用体变量中只能存放一个值。
? 共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员的值会被覆盖。
? 共用体变量的地址和它的各成员的地址都是同一地址。
? 共用体变量的初始化,但初始化表中只能有一个常量。
例如:union data a={123}; //初始化共用体为第一个成员
? 共用体变量所占的内存长度等于最长的成员的长度,而结构体变量所占的内存长度是各成员占的内存长度之和。
//共用体 #include <stdio.h> typedef union stu { char x; short int y; int z; double m; }STU; //sizeof(STU) = 8 int main(int argc,char *argv[]) { STU a={10}; union stu *p = &a; a.x = 5; a.y = 6; a.z = 15; printf("a.x+a.y = %d\n",a.x+a.y); //a.x+a.y=30,起作用的是最后一次存放的成员的值 printf("STU_len = %d\n",sizeof(STU)); //STU_len = 8,共用体变量所占的内存长度等于最长的成员的长度 printf("p = %p\n",p); //p = 0xbfdd7c84,共用体变量的地址和它的各成员的地址都是同一地址 printf("p->x = %p\n",&(p->x)); //p->x = 0xbfdd7c84 printf("p->y = %p\n",&(p->y)); //p->y = 0xbfdd7c84 printf("p->z = %p\n",&(p->z)); //p->z = 0xbfdd7c84 printf("p->m = %p\n",&(p->m)); //p->m = 0xbfdd7c84 return 0; }
三.枚举类型
将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。
? 枚举类型的定义
enum 枚举名
{
枚举值表
};
? 在枚举值表中应列出所有可用值,也称为枚举元素。
? 枚举变量仅能取枚举值所列元素。
例如:enum week //week为枚举类型
{
sun,mon,tue,wed,thu,fri,sat //枚举元素(枚举常量)
};
enum week workday,weekday; //workday、weekday为枚举变量
? workday与weekday只能取sun……sat中的一个
例如:workday = mon; //正确
weekday = tue //正确
workday = abc //错误,枚举之中没有abc
? 枚举类型的注意事项
1.枚举值是常量,不能在程序中用赋值语句再对它赋值。
例如:sun = 5; mon = 2; thu = hel; //都是错误的
2.每一个枚举元素都代表一个整数,C语言在编译时按定义时的顺序默认它们的值为0,1,2,3,……。
例如:在上面week的定义中,sun值为0,mon值为1,……,sat值为6
3.可以改变枚举值的默认值。
例如:enum week
{
sun=3,mon,tue,wed,thu,fri,sat
}; //此时sun=3,mon=4,tue=5,……以此类推……,sat=9
4.枚举元素可以用来作判断比较,枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。
例如:if(workday == mon) ......
if(workday > sun) ......
5.枚举变量就是一整型变量。
6.枚举也可以定义数组。
例如:enum week a[10];
//共用体 #include <stdio.h> enum week { sun = 2,mon,tue,wed,thu,fri,sat //mon = 3,tue = 4,……,sat = 9 }a,b,c; enum bool { false,true //false = 0,true = 1 }bl; int main(int argc,char *argv[]) { a = sun; b = mon; c = tue; printf("a = %d\n",a); //a = 2 printf("b = %d\n",b); //b = 3 printf("c = %d\n",c); //c = 4 // sun = 100; //错误,枚举值是常量,不可改 // printf("sun = %d\n",sun); a = 100; //枚举变量可以改 printf("a = %d\n",a); //a = 100 printf("a_len = %d\n",sizeof(a)); //a_len = 4,枚举变量就是一整型变量 bl = true; if(bl == true) printf("bl为真\n"); bl = 1; if(bl == true) //枚举元素可以用来作判断比较 printf("bl为真\n"); return 0; }
以上是关于结构体公用体枚举的主要内容,如果未能解决你的问题,请参考以下文章