结构体,联合体,枚举
文章目录
相应的关键字
关键字 | 说明 |
---|---|
struct | 结构体 |
union | 联合体 |
enum | 枚举 |
结构体
A.能够包含大量的变量并且对变量的数据类型无要求
B.结构体也是一种数据类型,它是自行定义的一种数据类型类比成一个int类型结构体分配空间是连续的,一个成员挨着一个成员
C.结构体的内存默认以4字节对齐
typedef关键字
作用:给数据类型取别名
语法:typedef 原数据类型 别名;
注意:别名后面加_t
例如
typedef signed int s32_t;
typedef unsigned int u32_t;
typedef struct student{
char name[10];
}stu_t;
.....
结构体的声明定义的使用方法:
方法1:直接定义结构体变量
struct {
结构体成员(字段);
}结构体变量名;
方法2:先声明结构体数据类型,然后用这种结构体数据类型定义结构体变量
声明:
struct 结构体名{
结构体成员(字段);
};
定义:
struct 结构体名 结构体变量名;
方法3:先用typedef关键字给一个声明的结构体数据类型取别名,,然后用别名定义结构体变量
声明:
typedef struct 结构体名{
结构体成员(字段);
}别名_t;
定义:
别名_t 结构体变量名;
例如
#include <stdio.h>
#include <string.h>
//方法2:声明
struct Human{
char name[30];
int age;
float height;
float weight;
};
//方法3:使用typedef关键字取别名
typedef struct human{
char name[30];
int age;
float height;
float weight;
}h_t;
int main(void){
//方法1:直接定义
struct{
char name[30];
int age;
float height;
float weight;
}human1;
//方法2:定义
struct Human hh;
//方法3:定义
h_t h;
return 0;
}
结构体的初始化方法:
A.普通始化方式
语法:
struct 结构体名/别名 结构体变量名={初始化值};
B.标记初始化方式
语法:
struct 结构体名/别名 结构体变量名={
.结构体成员=初始化值,
.结构体成员=初始化值,
…
};
C.结构体变量之间可以直接赋值
例如
#include <stdio.h>
typedef struct student{
char name[30];
int age;
}stu_t;
int main(void){
//普通初始化
stu_t stu1={"name",18};
//标记初始化
stu_t stu2={
.name="name",
.age=18
};
//直接赋值
stu_t stu3=stu2;
return 0;
}
结构体变量成员(字段)的访问
A.通过"."运算符来访问结构体变量的成员
语法:结构体变量名.成员名;
B. 通过’->"运算符开访问结构体指针变量
语法:结构体指针变量->成员名;
例如
#include <stdio.h>
typedef struct student{
char name[30];
int age;
}stu_t;
int main(void){
stu_t stu={
.name="学生",
.age=18
};
stu_t *pstu=&stu;
printf("学生名:%s 年龄:%d\n",stu.name,stu.age);
printf("name:%s age:%d\n",pstu->name,pstu->age);
return 0;
}
/*结构体成员韩式个结构体*/
#include <stdio.h>
//声明
typedef struct birthday{
int year;
int month;
int date;
}bir_t;
typedef struct student{
char name[30];
int age;
bir_t birthday1;
}stu_t;
int main(void){
//定义并初始化
stu_t stu={
.name = "学生",
.age=18,
.birthday={
.year=2021,
.month=4,
.date=30
}
};
//调用
stu_t *pstu=&stu;
printf("学生相关信息:%s %d %d %d %d\n"
stu.name,stu.age,stu.birthday.year,
stu.birthday.month,stu.birthday.date);
printf("studentdata:%s %d %d %d %d\n"
pstu->name,pstu->age,pstu->birthday.year,
pstu->birthday.month,pstu->birthday.date);
return 0;
}
函数和结构体,函数的形参
A. 直接传递结构体变量本身,形参是实参的一份拷贝,结构体有多大就需要拷贝多大函数通过形参是不能修改结构体实参,只是对形参进行改变
B.直接传递结构体变量的地址,函数通过形参可以直接修改结构体实参,代码执行效率高,如果是指针只需拷贝4字节
C.如果函数要访问结构体,将来要传递结构体指针,不要传递结构体变量,如果函数对结构体成员不进行修改,形参用const修饰
D.gcc对结构体成员编译时,对齐大小是根据结构成员最大占用内存大小对齐
通过#pragma pack()来修改对齐内存空间
例如
#include <stdio.h>
#include <string.h>
typedef struct A{
int a; //4 double 8
char b; //4 double 8
}a_t;
//以4字节对齐
typedef struct student{
char name[30];
int age;
float height;
}stu_t;
/*结构体作为函数的形参传递*/
void print(const stu_t *const pa){
printf("%s %d %g\n",pa->name,pa->age,pa->height);
}
/*结构体,作为函数的返回值*/
stu_t *modify(stu_t *pstu){
stu_t *pa=pstu;
strcpy(pa->name,"先生");
pa->age=20;
pa->height=2;
return pa;
}
int main(void){
//定义并初始化学生结构体变量
stu_t stu={
.name="学生",
.age=18,
.height=1.8
};
//调用print函数,打印stu_t这个结构体变量的值
print(&stu);
//调用modify函数
stu_t *pstu=modify(&stu);
print(pstu);
return 0;
}
联合体
A.它和结构体使用语法一摸一样,只是将关键字struct换成union
B.联合体中所有成员公用一块内存区域,优点节省内存
C.联合体占用的内存按成员中占内存最大的来算
例如
#include <stdio.h>
typedef union A{
int a; //4字节
char b; //1字节
}a_t; //4字节
int main(void){
//联合体数据类型中的成员a,b是共用用一块内存空间的
a_t a={.a=0x12345678};
if(0x78 == a.b){
printf("小端模式\n");
}else if(0x12 == a.b){
printf("大端模式\n");
}
printf("联合体的Byte大小:%ud\n",sizeof(a_t)); //4
return 0;
}
枚举
A.枚举的本质就是一堆整数的集合,列表,就是给整数取了个别名,提高代码的可读性枚举的值默认整数时从0开始,后面的成员依次加1
B.声明枚举数据类型的语法:
enum 枚举数据类型名{枚举值};
例如
#include <stdio.h>
enum COLOR{
RED=0,
GREEN,
BLUE
};
typedef enum{
RETURN_OK=0,
RETURN_NO,
}ret_t;
/*定义检测函数*/
ret_t check(const int a){
if( a!=0 ){
printf("成功了\n");
return RETURN_OK;
}else{
printf("失败了\n");
return RETURN_NO;
}
}
int main(void){
int a;
printf("清输入数字(0,1,2)显示对应颜色:");
scanf("%d",&a);
switch(a){
case RED:printf("红色\n");break;
case GREEN:printf("绿色\n");break;
case BLUE:printf("蓝色\n");break;
default:printf("未知颜色\n");
}
printf("%d\n",check(1));
return 0;
}