c语言结构体共用体枚举实例程序,10-C语言结构体-共用体-枚举

结构体是什么?

结构体和数组一样属于构造类型

数组是用于保存一组相同类型数据的,而结构体是用于保存一组不同类型的数组

定义结构体

在使用结构体之前必须先定义结构体类型,因为C语言不知道你的结构体中需要存储哪些类型的数据,我们必须通过定义结构体类型来告诉C语言,我们的结构体中需要存储哪些类型的数据

格式

struct 结构体名称{

数据类型 属性名称;

数据类型 属性名称;

... ...

};

struct Person{

char *name;

int age;

double height;

};

// 注意:结尾有分号

定义结构体变量

格式: struct 结构体名 结构体变量名;

struct Person p;

// Person 结构体名

// p 结构体变量名

使用结构体变量

结构体变量名称.结构体属性名称;

p.name = "cww";

p.age = 35;

p.height = 1.9;

printf("name = %s\n", p.name);

printf("age = %i\n", p.age);

printf("height = %lf\n", p.height);

结构体变量初始化的几种方式

定义的同时按顺序初始化

struct Person{

char *name;

int age;

double height;

};

struct Person p = {"cww", 18, 1.8};

定义的同时不按顺序初始化

struct Person{

char *name;

int age;

double height;

};

struct Person p = {.age = 35, .name = "cww", .height = 1.8};

先定义后逐个初始化

struct Person{

char *name;

int age;

double height;

} P;

p.name = "cww";

p.age = 18;

p.height = 1.8;

先定义后一次性初始化(不推荐使用)

struct Person {

char *name;

int age;

double height;

} P;

P = (struct Person){"cww", 18, 1.8}

定义结构体变量的几种方式

先定义结构体类型,再定义结构体变量

struct Person{

char *name;

int age;

double height;

};

struct Person p1;

定义结构体类型的同时定义结构体变量

struct Person{

char *name;

int age;

double height;

} p2;

定义结构体类型的同时省略结构体名称,同时定义结构变量(匿名结构体)

特点: 结构体类型之能使用一次;

struct {

char *name;

int age;

double height;

} p3;

结构体类型作用域

结构类型定义在函数内部的作用域与局部变量的作用域是相同的

从定义的哪一行开始,直到遇到return或者大括号结束

#include

void test();

int main()

{

struct Person{

char *name;

int age;

double height;

};

struct Person p;

p.name = "cww";

p.age = 18;

p.height = 1.8;

printf("name = %s\n", p.name);

test();

return 0;

}

void test(){

printf("name = %s\n", p.name); // 报错

}

结构类型定义在函数外部的作用域与全局变量的作用域是相同的

从定义的哪一行开始,知道文件结束为止

#include

struct Person{// 定义全局结构体

char *name;

int age;

double height;

} ;

void test();

int main()

{

struct Person p;

p.name = "cww";

p.age = 18;

p.height = 1.8;

printf("name = %s\n", p.name); // cww

test();

return 0;

}

void test(){

struct Person p2; //可以使用全局的结构体

p2.name = "ppp";

printf("name = %s\n", p2.name); // ppp

}

结构体数组

结构体数组和普通数组并无太大差异,只不过是数组中的元素都是结构体而已

格式: struct 结构体类型名称 数组名称[元素个数];

struct Person {

char *name;

int age;

};

struct Person p[2];

结构体数组初始化和普通数组也一样,分为先定义后初始化和定义同时初始化;

定义的同时初始化

struct Person {

char *name;

int age;

};

struct Person p[2] = {{"cww",18}, {"ppp", 20}};

- 先定义后初始化

```

struct Person {

char *name;

int age;

};

struct Person p[2];

p[0] = {"cww", 18};

p[1] = {"ppp", 20};

```

结构体内存分析

注意点:

给整个结构体变量分配存储空间和数组一样,从内存地址比较大的开始分配

给结构体变量中的属性分配存储空间也和数组一样,从所占用内存地址比较小的开始分配

注意点:

和数组不同的是,数组名保存的就是数组首元素的地址

而结构体变量名, 保存的不是结构体首属性的地址

#include

int main()

{

struct Person {

int age;

double height;

};

struct Person p;

// 结构体变量的名称并没有保存结构体首属性的地址;

printf("p = %p\n", p); // 00401770

printf("&p = %p\n", &p); // 0028FEB0

return 0;

}

结构体在分配内存的时候,会做一个内存对齐的操作(并不是都按最大属性字节分配)

会先获取所有属性中,占用内存最大的属性的字节

然后再开辟最大属性字节的内存给第一个属性

如果分配给一个属性之后还能继续分配给第二个属性,那么继续分配

如果分配给第一个属性之后,剩余的内存不够分配给第二个属性,那么会再次开辟最大属性字节的内存,再次分配

以此类推

```

struct Person{

int age; // 4

char ch; // 1

double score; // 8

};

struct Person p;

printf("sizeof = %i\n", sizeof(p)); // 16

```

- 调换顺序

```

struct Person{

int age; // 4

double score; // 8

char ch; // 1

};

struct Person p;

printf("sizeof = %i\n", sizeof(p)); // 24

```

结构体指针

因为结构体变量也会分配内存空间,所以结构体变量也有内存地址,所以也可以使用指针保存结构体变量的地址

规律:定义指向结构体变量的指针和过去定义指向普通变量的指针一样

struct Person {

int age;

double height;

};

struct Person per = {22, 1.8};

struct Person *p;

// p = per; // 错误写法, 写法和普通变量一样

p = &per; // 正确写法,要在变量前面添加取地址符号 &;

printf("per = %p\n", &per); // 0028FEA8;

printf("p = %p\n", p); // 0028FEA8;

如果指针指向了一个结构体变量,那么访问结构体变量的方式有3种

1.结构体变量名称.属性名称

2.(*结构体指针变量名称).属性名称;

3.结构体指针变量名称->属性名称;

1.结构体变量名称.属性名称

printf("per.age = %i\n", per.age); // 22

2.(*结构体指针变量名称).属性名称;

printf("per.age = %i\n", (*p).age); // 22

3.结构体指针变量名称->属性名称;

printf("per.name = %i\n", p->age); // 22

结构体嵌套定义

结构体的属性可以又是一个结构体

如果某个成员也是结构体变量,可以连续使用成员运算符 "." 访问低一级的成员

#include

int main()

{

// 定义一个日期的结构体

struct Date{

int year;

int month;

int day;

};

// 定义一个人的结构体

struct Person{

char *name;

int age;

// 嵌套定义

struct Date birthday;

};

// 完全初始化

struct Person p = {"cww", 18, {2020,02,20}};

printf("name = %s\n", p.name); // cww

printf("year = %i\n", p.birthday.year); // 2020

printf("day = %i\n", p.birthday.day); // 20

return 0;

}

结构体和函数

结构体变量之间的赋值和基本数据类型一样,是值拷贝

#include

int main()

{

struct Person{

char *name;

int age;

};

struct Person p1 = {"cww", 18};

struct Person p2;

p2 = p1;

p2.name = "ppp"; // 修改p2不会影响p1 是值拷贝

printf("p1.name = %s\n", p1.name); // cww

printf("p2.name = %s\n", p2.name); // ppp

return 0;

}

注意:

定义结构体类型不会分配存储空间

只有定义结构体变量才会分配存储空间;

结构体变量作为函数形参时也是值传递,在函数内修改形参,不会影响外界实参

#include

struct Person{

char *name;

int age;

};

void test(struct Person p);

int main()

{

struct Person p1 = {"cww", 18};

printf("p1.name = %s\n", p1.name); // cww

test(p1);

printf("p1.name = %s\n", p1.name); // cww

return 0;

}

void test(struct Person p){

p.name = "hhh";

printf("p1.name = %s\n", p.name); // hhh

}

共用体

共用体和结构体不同的是,结构体的每个成员都是占用一块独立的存储空间,而共用体所有成员占用同一块存储空间

定义共用体格式:

union 共用体名称{

数据类型 属性名称;

数据类型 属性名称;

... ...

};

union Test{

int age;

char ch;

};

定义共用体类型变量格式: union 共用体名 共用体变量名称

union Test t;

应用场景:

1.通信中的数据包会用到共用体

2.节约内存

3.需要大量的临时变量,这些变量类型不同

共用体定义的格式和结构体只有关键字不一样,结构体用struct,共用体用 union

共用体特点:

结构体的每个属性都会占用一块单独的存储空间,而共用体所有的属性都共用同一块存储空间

只要其中一个属性发生了改变, 其他的属性都会受到影响

#include

int main()

{

union Test {

int age;

char ch;

};

union Test t;

printf("sizeof(t) = %i\n", sizeof(t)); //4

t.age = 18;

printf("t.age = %i\n", t.age); // 18

t.ch = 'a';

printf("t.ch = %c\n", t.ch); // a

printf("t.age = %i\n", t.age); // 97

return 0;

}

枚举

枚举用于提升代码的阅读性, 一般用于表示几个固定的值

应用场景: 如果某些变量的取值是固定的, 那么就可以考虑使用枚举来实现;

格式:

enum 枚举类型名称{

取值1,

取值2,

};

注意点: 和结构体不同,枚举是用逗号隔开

enum Gender{

male,

female,

};

规范:

枚举的取值一般是以K开头,后面跟上枚举类型名称,后面再跟上表达的含义

K代表这是一个常量

枚举类型名称,主要是为了有多个枚举的时候,方便区分

含义,你想要定义名字

enum Gender{

KGenderMale, // 0

KGenderFemale, // 1

// 2 ... ...

};

枚举的取值:

默认的情况下, 是从0开始取值,依次递增

也可以手动指定从几开始,依次递增;

enum Gender{

KGenderMale = 6, // 6

KGenderFemale, // 7

// 8 ... ...

};

枚举类型的作用域

和结构体类型的作用域一样,和变量的作用域一样

#include

int main()

{

enum Gender {

KGenderMale,

KGenderFemale,

};

printf("KGenderFemale = %i\n", KGenderFemale); // 1

return 0;

}

#include

int main()

{

{

enum Gender {

KGenderMale,

KGenderFemale,

};

}

printf("KGenderFemale = %i\n", KGenderFemale); // 报错

return 0;

}

枚举类型变量的多种定义方式

和结构体类型的多种定义方式一样

// 先定义枚举类型,再定义枚举变量

enum Gender{

kGenderMale,

KGenderFemale,

}

enum Gender g1;

// 定义枚举类型的同时,定义枚举变量

enum Gender{

KGenderMale,

KGenderFemale,

} g2;

// 定义枚举类型的同时,定义枚举变量,并且省略枚举类型名称

enum {

KGenderMale,

KGenderFemale,

} g3;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值