1.1.1 结构概念
1.结构存在的意义
存在是合理的,许多事物的存在是在不断解决问题引入的,当然有更好的方法出现时改变也是合理的。在实际问题中,一组数据往往具有不同的数据类型。例如,在学生登记表中,姓名应为字符型,学号可为整型或字符型,年龄应为整型,性别应为字符型,成绩可为整型或实型。显然不能用一个数组来存放这一组数据,因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C语言中给出了另一种构造数据类型—“结构(structure)”或叫“结构体”,它相当于其他高级语言中的记录。“结构”是一种构造类型,它是由若干“成员”组成的,每一个成员可以是一个基本数据类型或者又是一个构造类型。结构既是一种“构造”而成的数据类型,那么在说明和使用之前必须先定义它,也就是先构造它,如同在声明和调用函数之前要先定义函数一样。
定义一个结构的一般语法形式如下:
struct 结构名
{
成员表列
};
成员表列由若干个成员组成,每个成员都是该结构的一个组成部分。对每个成员也必须作类型说明,其形式如下:
类型说明符 成员名;
成员名的命名应符合标识符的书写规定。结构定义举例说明如下:
struct stu
{
int num;
char name[20];
char sex;
float score;
};
在这个结构定义中,结构名为stu,该结构由4个成员组成。第一个成员是num,为整型变量;第二个成员是name,为字符数组;第三个成员是sex,为字符变量;第四个成员是score,为实型变量。应注意在括号后的分号是不可缺少的。结构定义之后,即可进行结构变量定义,凡定义为结构stu的变量都由上述4个成员组成。由此可见,结构是一种复杂的数据类型,是数目固定,类型不同的若干有序变量的集合。
2.结构概念小结
结构是一种构造数据类型。
结构的用途是把不同类型的数据组合成一个整体,是自定义数据类型。
结构类型定义语法形式如下:
struct [结构名]
{
类型标识符 成员名;
类型标识符 成员名;
……………
}[变量名1, 变量名2……];
定义结构变量方法为:struct 结构名 变量名。
结构变量引用规则为:结构变量不能整体引用,只能引用变量成员,引用方式为结构变量名.成员名,可以将一个结构变量赋值给另一个结构变量,结构嵌套时需要逐级引用。
1.1.2 结构变量
1. 结构变量有以下三种定义方法
(1) 先定义结构,再定义结构变量
struct stu
{
int num;
char name[8];
char sex;
float score;
};
struct stu boy1,boy2;
(2) 在定义结构类型的同时定义结构变量
struct stu
{
int num;
char name[8];
char sex;
float score;
}boy1,boy2;
(3) 直接定义结构变量
struct
{
int num;
char name[8];
char sex;
float score;
}boy1,boy2;
第三种方法与第二种方法的区别在于第三种方法中省去了结构名,而直接给出结构变量。三种方法中说明的boy1、boy2变量都具有下图6-2所示的结构。
num name sex score
|
|
|
|
图6-2 结构变量组成图
2. 结构变量内存布局
所有C语言中的变量经过编译后都会转换为对内存线性地址的操作。各种变量的引入是面向人类思维进行的,方便人们高效的编程,而C语言源代码经过gcc编译后,形成执行码时,所有变量与符号失去意义,变量与符号转变为对相应内存地址的操作。int类型代表着4个字节相应地址的内存空间的抽象,而结构变量也是代表着一片内存空间的抽象(结构名不代表内存地址),所以相同类型结构变量与int类型变量一样可以用=号直接赋值(如boy2=boy1),两个结构变量用=号赋值代表两片相同大小空间的复制拷贝。
内存的物理地址是线性的,一维的,而结构变量往往代表二维或多维。这种二维或多维结构是方便人们编程时对变量进行管理,是一种面向人们思维的逻辑结构,但结构变量最终物理表现在内存中还是一维线性结构。
下面以上面定义的boy1来说明结构变量在内存中存储方式。表6-4列出了结构变量boy1的内存布局,此时boy1代表着-19到0这片内存空间的抽象。&boy1代表结构变量的地址,即为0。结构成员(如boy1.num)其实也代表着对应地址内存空间的抽象,对结构成员的操作编译器最后会转化为对相应内存地址的操作。
表6-4 boy1结构变量内存布局表
假定栈空间起始地址为0 | ||
内存地址 | 内存 | 说明 |
0 | boy1.num |
|
-1 | ||
-2 | ||
-3 | ||
-4 | boy1.name[7] |
|
-5 | boy1.name[6] |
|
-7 | boy1.name[5] |
|
-8 | boy1.name[4] |
|
-9 | boy1.name[3] |
|
-10 | boy1.name[2] |
|
-11 | boy1.name[1] |
|
-12 | boy1.name[0] | body.name表示内存地址-12 |
-13 | boy1.sex |
|
-14 |
| float为4个字节,需要-16处才能对齐,所以空两个字节 |
-15 |
| |
-16 | boy1.score |
|
-17 | ||
-18 | ||
-19 |
3. 结构变量成员的引用
表示结构变量成员引用的一般形式如下:
结构变量名.成员名
例如:
boy1.num 即第一个人的学号
boy2.sex 即第二个人的性别
如果成员本身又是一个结构则必须逐级找到最低级的成员才能引用。
4. 结构变量的赋值
结构变量的赋值就是给各成员赋值,可用输入语句或赋值语句来完成。
【例6-4】给结构变量赋值并输出其值。
stru1.c源代码如下:
#include <stdio.h>
int main()
{
struct stu
{
int num;
char name[20];
char sex;
float score;
} boy1,boy2;
boy1.num=102;
boy1.name="Zhang ping";
printf("input sex and score\n");
scanf("%c %f",&boy1.sex,&boy1.score);
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score);
return 0 ;
}
编译 gcc stru1.c -o stru1。
执行 ./stru1, 执行结果如下:
input sex and score
M 90
Number=102
Name=Zhang ping
Sex=M
Score=90.000000
5. 结构变量的初始化
【例6-5】对结构变量初始化。
stru2.c源代码如下:
#include <stdio.h>
int main()
{
struct stu
{
int num;
char *name;
char sex;
float score;
}boy2,boy1={102,"Zhang ping",'M',78.5};
boy2=boy1;
printf("Number=%d\nName=%s\n",boy2.num,boy2.name);
printf("Sex=%c\nScore=%f\n",boy2.sex,boy2.score);
return 0 ;
}
编译 gcc stru2.c -o stru2。
执行 ./stru2, 执行结果如下:
Number=102
Name=Zhang ping
Sex=M
Score=78.500000
6. 结构数组的定义
结构数组的定义与初始化方法如下:
struct stu
{
int num;
char name[20];
char sex;
float score;
}boy[5]={
{101,"Li ping","M",45},
{102,"Zhang ping","M",62.5},
{103,"He fang","F",92.5},
{104,"Cheng ling","F",87},
{105,"Wang ming","M",58},
};
当对全部元素作初始化赋值时,也可不给出数组长度。
引用结构数组成员的方法如下:
结构[下标].成员变量
如boy[0].num, boy[1].name
摘录自《深入浅出Linux工具与编程》