一,结构体
1,定义结构体类型:结构体名与成员表列
struct Date //结构体名(大写以突出)
{
int month;
int day;
int year; //成员表列
};//最后要有一个分号!!
//建立了一个结构体类型之后,Date就成为了一个新的变量类型
struct Student
{
char name[20];
float score;
struct Date birthday; //成员可以属于另一个结构体类型,即结构体可以嵌套(定义在先)
};
注意:变量类型 ≠ \not= = 变量
2,结构体变量的定义
struct Student s1,s2;//定义结构体类型的变量(可以先声明再定义)
/*也可以在声明类型的同时定义变量:
struct Student
{
char name[20];
float score;
struct Date birthday;
}s1,s2;
*/
/*若该结构体类型只用一次,也可以不命名,直接定义
struct
{
char name[20];
float score;
struct Date birthday;
}s1,s2;
*/
3,结构体变量的初始化
可以在定义时或者定义之后对结构体初始化。一般情况下都是在定义的同时进行初始化,因为那样比较方便。如果定义之后再进行初始化,那就只能一个一个的对成员进行赋值(就如同数组一样,数组只能在定义的时候才可以一次性对所有元素进行初始化,如果定义之后再初始化就只能一个一个的赋值了),那样比较麻烦。
struct Student s1 = {
"shao", 100, {
5, 17, 2002}};//方便
/*或:
struct Student s1;
strcpy(s1.name, "shao");//注意:字符串不能直接赋值,要用strcpy函数
s1.score = 100;
s1.birthday.month = 5;//需要逐级找到最低级的成员才能使用
... */
4,结构体数组
每个元素都是一个结构体变量
struct employee
{
int num;
char name[20];
float salary;
}emp[3] = {
{
001, "lemon", 2000},
{
002, "apple", 2300},
{
003, "peach", 2500}
};
5,结构体变量作函数参数
#include <stdio.h>
struct Student
{
int num;
float score[3];//结构体中存在数组成员
float aver;
};
void input(struct Student stu[])
{
int i;
for (i = 0; i < 3; i ++)
{
scanf("%d %f %f %f", &stu[i].num, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);//数组成员的元素要一个一个单独输入
stu[i].aver = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;//不用输入aver,因为该值是计算出来的
}
}
struct Student max(struct Student stu[])//函数的类型也要用结构体类型
{
//函数运行的结果为一个结构体数组的元素
int i, m = 0;
for (i = 0; i < 3; i ++)
if (stu[i].aver > stu[m].aver)
m = i;//用m来存放成绩最高的学生在数组中的序号
return (stu[m]);
}
void print(struct Student stud)//该函数的形参是一个变量而不是一个数组,直接将变量的信息传递过来而不是地址
{
printf("%d %lf %lf %lf", stud.num, stud.score[0], stud.score[1], stud.score[2]);
}
int main()
{
struct Student stu[3];
input(stu);
print(max(stu));//简化主程序
return 0;
}
在形参的位置使用结构体变量,在函数调用期间,形参也要占用内存。因此这种传递方式在空间和时间上开销都比较大。另外“值传递”使得若在函数内修改了变量的值,这种改变不会返回到主程序中。
6,结构体变量的指针作函数参数
#include <stdio.h>
struct Student
{
int num;
float score[3];
float aver;
};
void input(struct Student *p)
{
int i;
for (i = 0; i < 3; i ++, p ++)
{
scanf("%d %f %f %f", &(*p).num, &(*p).score[0], &(*p).score[1], &(*p).score[2]);
p->aver = (p->score[0] + p->score[1] + p->score[2]) / 3.0;
}
}
struct Student max(struct Student stu[])//函数的类型也要用结构体类型
{
//函数运行的结果为一个结构体数组的元素
int i, m = 0;
for (i = 0; i < 3; i ++)
if (stu[i].aver > stu[m].aver)
m = i;//用m来存放成绩最高的学生在数组中的序号
return (stu[m]);
}
void print(struct Student stud)//该函数的形参是一个变量而不是一个数组,直接将变量的信息传递过来而不是地址
{
printf("%d %lf %lf %lf", stud.num, stud.score[0], stud.score[1], stud.score[2]);
}
int main()
{
struct Student stu[3], *p = stu;
input(p);
print(max(p));
return 0;
}
二,共用体
共用体变量的定义方式与结构体变量很相似
union Data
{
int i;
char ch;
}a, b, c;
值得注意的是:结构体变量大小是所包含的成员所占字节数的总和,其中每个成员都有自己的内存单元;共用体的大小为所包含成员中的最大内存长度。
共用体变量的地址与各成员的地址都是同一地址。
尽管共用体内的各成员共用一段内存,但引用时只能引用成员而不能直接引用共用体变量。printf("%d", a);
是错误的。
对共用体变量进行初始化时,只需一个初始化值就够了,其类型应与共用体内第一个成员的类型相同。
在共用体中只有一个成员起作用。
#include<stdio.h>
union Data
{
int i;
char ch;
}a;
int main()
{
a.i = 97;//看按照什么形式来进行存储
printf("%d %c", a.i, a.ch);//根据内存单元中的信息来进行使用
union Data c = {
1, 'a'};//初始化表中只能有一个常量,起作用的只是最后一次赋值的量,因为所有二进制位都会覆盖(取代)
printf("\n%d", a.i); //会输出97
return 0;
}