1、结构体定义
(1)、结构类型:在C语言中,关键字struct能定义各种类型的变量集合,并把它们视为一个整体,称为结构
结构体的定义:
1、声明结构体模板
2、定义结构体变量
(2)、结构类型的定义方法
struct 结构体名
{
数据类型 成员1名;
数据类型 成员2名;
......
数据类型 成员n名;
};
(3)、结构类型不同于结构类型变量
·结构类型名并不是结构体变量名,只是一个标签。
·结构体模板只是声明了一种数据类型,定义了数据的组织形式,并未声明结构体类型的变量
·编译器不为结构体模板分配内存
int i;
//int 是类型名,i是int类型的变量
struct student s1;
//struct student 是类型名,s1是struct student类型的变量
2、结构类型变量的定义
三种方法:
方法1:先定义结构体模板,再定义变量名
struct student
{
long stuID;
char stuName[10];
char stuSex;
char birthYear;
int mathScore;
};
struct student stu1;
//stu1为struct student类型的变量
方法2:在定义类型的同时定义变量
struct student
{
long stuID;
char stuName[10];
char stuSex;
char birthYear;
int mathScore;
}stu1;
//stu1为struct student类型的变量
方法3:不指定结构体标签,直接定义结构体变量
struct
{
long stuID;
char stuName[10];
char stuSex;
char birthYear;
int mathScore;
}stu1;
//stu1为struct student类型的变量
3、使用typedef定义数据类型别名
为现有的数据类型定义一个别名
typedef short INT16;
别名通常使用大写字母
并未定义一个新的数据类型
定义后别名和原名具有相同的功能,可以互换
INT16 i,j;
short k;
为结构体定义别名
typedef struct student
{
long stuID;
char stuName[10];
char stuSex;
char birthYear;
int mathScore;
}STUDENT;
//typedef struct student STUDENT;
//STUDENT 为 struct student 的别名
定义后别名与原名通用:如
struct student stu1;
STUDENT stu1;
4、嵌套的结构类型
在一个结构体内其成员可以是另外一个结构体
不可以嵌套同类型的结构体
typedef struct date
{
int year;
int month;
int day;
}DATE;
struct student
{
long studentID;
char studentName[10];
char studentSex;
DATE birthday;//被嵌套的结构体,还有一种写法为:struct date birthday;
int mathScore;
};
5、结构变量的初始化
(1)、不嵌套情形
struct student stu1 = {100010,"令狐冲",'M',95};
STUDENT stu1 = {100010,"令狐冲",'M',95};
(2)、嵌套情形
STUDENT stu1 = {100010,"令狐冲",'M',{1991,5,19},95};
6、结构变量的引用
(1)、圆点运算符:
结构体变量名.成员名
stu1.stuID = 100012;
(2)、嵌套情形:以级联方式逐级访问
stu1.date.year = 1990;
stuYear = stu1.date.year;
7、结构变量的整体赋值
1、允许同类型的结构体变量之间赋值
struct student stu1,stu2;
stu2 = stu1;
2、但不允许用{}整体赋值
stu1 = {100010,"令狐冲",'M',95};//错误
3、字符数组赋值时需要使用strcpy()
stu1.name = "令狐冲";//错误
strcpy(stu1.name,"令狐冲");//正确
8、结构变量的赋值和引用的方法
例1、用结构体变量存储一个学生的信息,包括学号、姓名、性别、生日、4门课的成绩
#include
typedef struct date
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
long studentID;
char studentName[10];
char studentSex;
DATE birthday;
int mathScore;
}STUDENT;
int main()
{
STUDENT stu1,stu2;
int i;
printf("Input a record:\n");
scanf("%ld",&stu1.studentID);
scanf("%s",stu1.studentName);//数人学生姓名,无需加&
scanf(" %c",&stu1.studentSex);
scanf("%d",&stu1.birthday.year);
scanf("%d",&stu1.birthday.month);
scanf("%d",&stu1.birthday.day);
for(i = 0;i < 4;i++)
{
scanf("%d",&stu1.score[i]);
}
stu2 = stu1;//同类型结构体变量之间的赋值操作
printf("&stu2 = %p\n",&stu2);//打印结构体变量stu2的地址
return 0;
}
9、结构变量及成员的地址
10、结构变量所占内存的字节数
通常不是各成员所占字节数的总和,对于多数计算机系统,存在内存的地址对齐问题,以提高访问效率和运算速度
结构体默认的字节对齐一般满足三个准则:
1、结构体变量的首地址能够被其最宽基本类型,成员的大小所整除
2、结构体每个成员相对于结构体首地址的偏移都是成员自身大小的整数倍,如有需要编译器会在成员之间加上填充字节
3、结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会在最末一个成员之后加上填充字节
(一)、结构数组
1、结构数组定义
下面定义一个结构数组stu1,共有30个元素,stu[0]~stu[29].每个数组元素都具有struct student的结构形式
struct student
{
int num;
char name[20];
char sex;
float score;
}stu[30];
1、结构数组元素的成员引用
结构体数组名[[下标].结构体成员名
2、使用方法与同类型的变量完全相同
stu[5].age = 26;
strcpy(stu[5].name,"Xiao Ming"
stu[4] = stu[1];
例2、【结构数组排序】:输入n并输入n(n<=10)个学生的信息(学号、姓名、成绩),按照从高分到低分的顺序输出他们的信息。
#include
struct student
{
int num;
char name[20];
int score;
};
int main(void)
{
struct student stud[10];//定义结构数组
int n;
int i;
int j;
int temp;
scanf("%d",&n);
//输入
for( i = 0;i < n;i++)
{
scanf("%d%s%d",&stud[i].num,stud[i].name,&stud[i].score);
}
//对成绩进行排序
for( i = 0;i < n - 1;i++)
{
for(j = i+1;j < n;j++)
if(stud[j].score > stud[i].score)
{
temp = stud[j].score;
stud[j].score = stud[i].score;
stud[i].score = temp;
}
}
//输出
for( i = 0;i < n;i++)
{
printf("%d,%s,%d",stud[i].num,stud[i].name,stud[i].score);
printf("\n");
}
return 0;
}
运行结果:
(二)、结构指针
1、结构指针:指向结构类型变量的指针
结构类型名 *指针变量名
例如:
struct student stu1 = {1,"李芳",45};
struct student *p;
p = &stu1;
(1)、用*p访问结构成员
(*p).num = 36;
(2)、用指向运算符“->”访问结构成员
p->num = 36;
当p=&stu1时,以下三条语句相同
stu1.num = 36;
(*p).num = 36;
p->num = 36;
3、结构成员的多种访问方法
例3、结构体成员的访问方式
struct employee
{
char name[20];
int age;
int tel;
};
int main(void)
{
struct employee empl = {"Livang",22,15424654664};
struct employee *p;
p = &empl;
printf("%s %d %d\n",empl.name,empl.age,empl.tel);
printf("%s %d %d\n",(*p).name,(*p).age,(*p).tel);
printf("%s %d %d\n",p->name,p->age,p->tel);
return 0;
}
(三)、使用指针访问结构体数组
1、一个指针变量可以访问普通数组,也可以访问结构体数组
2、如果p的初值为指向数组的第一个元素,则p++后为指向下一个元素的起始地址
3、如果指针p已定义为指向结构体类型的数据,则它只能指向一个结构体类型数据(即一个元素的起始地址),而不能指向一个元素中的某一成员
例4、使用指针访问结构体数组
struct employee
{
char name[20];
int age;
int tel;
};
int main()
{
struct employee emp[3] = {{"Livang",22,45646},{"Wangming",34,78465},{"Zhaoli",45,56487}};
struct employee *p;
printf("name age tel\n");
for(p = emp;p < emp + 3;p++)
{
printf("%-8s%-6d%-8ld",p->name,p->age,p->tel);
}
return 0;
}