C语言基础级——结构体
结构体目录
设计程序最重要的是选择一个表示数据的好方法。简单的变量、数组到复杂些的结构体、共同体和枚举,能够使数据表示形式更加地丰富、可观。
奶制品营养成分有能量(KJ)、蛋白质(g)、碳水化合物(g)等元素,市面上几种牛奶参数列表为:
奶制品 | 能量(KJ) | 蛋白质(g) | 碳水化合物(g) |
---|---|---|---|
豆本豆奶(SOY) | 250 | 3.0 | 2.0 |
伊利(Yili) | 277 | 3.2 | 4.8 |
蒙牛(Mon) | 182 | 3.0 | 4.9 |
1. 结构体
完成结构体一系列动作三部曲:
- 建立结构体的模板
- 声明引入模板的变量
- 对结构体各个成员进行访问
1.1 声明
奶制品营养成分有三种,采用结构体声明,如下:
struct milk
{
int energy;
float protein;
float carbohydrate;
};
-
milk是一个可选的标记。
-
该声明有
三
个成员,一个是int
类型,两个是float
类型。 -
结构体声明并没有创建出一个实际的数据对象,我们可以认为它是属于模板。这个模板是适用于豆本豆(SOY_MILK),伊利(Yili_MILK),蒙牛(Mon_MILK)的奶制品。
所以我们还需要做以模板为标准创建出三个结构体变量,这三个结构体变量分别可以存放不同的奶制品参数。看到接下来这条指令之后,编译器使用milk
模板为 SOY
、Mon
、Yili
分配内存空间,如下:
// 可放在函数内部和外部, 且声明之后, 将会为其分配内存空间。
struct milk SOY;
struct milk Mon;
struct milk Yili;
如果只需要使用一个结构体变量,通常可选的标记为小写,而结构体类型名为首字母大写。以豆本豆为例,如下:
struct milk
{
int energy;
float protein;
float carbohydrate;
} SOY;
// 还是适用
struct milk Mon;
struct milk Yili;
这样写的话,代码可读性明显降低。(注意:我们还可以把可选标记去掉,让此结构体只用于豆本豆),如下:
struct
{
int energy;
float protein;
float carbohydrate;
} SOY;
// 不适用
struct milk Mon;
struct milk Yili;
// 再建立新的结构体, 这样才适用。
struct
{
int energy;
float protein;
float carbohydrate;
} Mon;
1.2 初始化
数组其中的一种初始化:
int a[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
那么,结构体的初始化和数组的相似的,有三种方式:
- 第一种
struct milk
{
int energy;
float protein;
float carbohydrate;
};
struct milk SOY = {
250,
3.0,
2.0
};
- 第二种 C99标准还支持:
struct milk
{
int energy;
float protein;
float carbohydrate;
};
// 部分初始化
struct milk SOY = {
.energy = 250,
};
// 全部初始化
struct milk SOY = {
.energy = 250,
.protein = 3.0,
.carbohydrate = 2.0
};
- 第三种 重定义初始化:
typedef struct
{
int energy;
float protein;
float carbohydrate;
} milk;
milk SOY = {
250,
3.0,
2.0
};
1.3 访问结构体成员
1.3.1 (.) 和 (->) 区别
1.3.1.1 (.) 成员运算符
- 成员选择为对象(
.
),可读作“的”。 - 第
13
行,是结构体变量(SOY
)“的” 能量(energy
) 等于250
,如下:
#include<stdio.h>
struct milk
{
int energy;
float protein;
} ;
// 声明结构体变量
struct milk SOY;
int main()
{
// 通过结构体变量进行访问
SOY.energy = 250;
SOY.protein = 2.0;
printf("%d\n", SOY.energy);
printf("%f\n", SOY.protein);
return 0;
}
1.3.1.2 (->) 间接运算符
- 成员选择为指针(
->
),表示为指向结构体的指针。 - 第
19
行,通过指针变量(SOYPtr
)访问结构体变量(SOY
)的能量(energy
)成员的地址。 - 与普通的变量指针用法相似。如下:
#include<stdio.h>
struct milk
{
int energy;
float protein;
} ;
// 声明结构体变量
struct milk SOY;
// 声明结构体指针变量
struct milk *pSOY;
int main()
{
// 这一步不能省略,否则将会出现段错误。
pSOY = &SOY;
// 通过指针变量进行访问
pSOY->energy = 250;
pSOY->protein = 2.0;
printf("%d\n", pSOY->energy);
printf("%f\n", pSOY->protein);
return 0;
}
1.4 typedef
typedef
是一种高级数据特性,可以给某一个类型创建新的名字,为了能够为经常出现的类型创建一个方便的、可识别的名称,如下:
// 声明结构体
typedef struct
{
int energy;
float protein;
float carbohydrate;
} Milk;
// 声明结构体变量
Milk SOY;
Milk Mon;
Milk Yili;
浅谈,我们在单片机程序应用当中,常常会使用typedef
给某些类型重新命名来使用(今后会出一个专题讲解宏定义与重命名区别),如下:
typedef unsigned char BYTE;
typedef char* STRING;
#include<stdio.h>
// 重命名uchar类型与char*
typedef unsigned char BYTE;
typedef char* STRING;
int main()
{
BYTE param = 'H';
STRING str = "Home";
printf("%c\n", param);
printf("%s\n", str);
return 0;
}