结构体枚举和共用体
一.结构体的定义:
使用结构体之前必须定义;
struct 结构体名
{
类型标识符 成员名1;
类型标识符 成员名2;
…………
…………
}; 分号必不可少;
例如,日期定义:
struct date
{
int month;
int day;
int year;
};
注意以下几点:
1. 成员类型可以是除本身以外的任何已有类型;也可以是自己结构体的指针;
2. 定义在函数之外,全局作用域;定义在一对花括号内,在花括号内有效;
3. 结构体的定义不分配空间,只有定义了结构体类型的变量,才分配空间;
4. 成员名可以和程序中的变量名相同,而这不代表同一个对象;
5. 若两个结构体出结构体名外,其他均相同,也是两个不同的结构体;
二. 结构体变量的定义:(经典的三种形式):
1. 先定义类型,再定义结构体变量;
struct stu
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
};
struct stu boy1,boy2;
2. 在定义结构体类型的同时定义结构体变量;
struct stu
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
}boy1,boy2;
3. 直接定义结构体变量:
struct
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
}boy1,boy2;
结构体变量的引用和初始化:
引用结构体变量成员的一般形式:
结构变量名.成员名 . 成员运算符,所有运算符中的优先级最高;
例如: boy1.num boy2.sex
当使用指针的时候:
结构变量名 - > 成员名
例:
struct msg_st
{
int a;
};
struct msg_st msg;
struct msg_st *ms;
msg.a = 10;
ms->a = 20;
注意的几个问题:
1. 不能将一个结构体变量作为整体输出:
例如: printf("%d,%s",boy1); 是错误的;
应当对成员分别输出;
2. 如果成员本身也是一个结构体,要用多个.逐级找到最低一级的成员: boy1.birthday.month;
3. 成员变量可以进行运算:
但是若要给boy1赋予姓名,boy1.name="Li ping"是错误的;
要用strcpy(boy1.name,"Li Ping")
两个类型相同的结构体变量(结构体名相同)可以互相赋值: boy1=boy2 ( 内容全部复制 )
结构体变量的初始化:
例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
struct stu
{
unsigned int num;
char name[20];
char sex[2];
int age;
float score;
}boy1, boy2;
printf("Please Input your student number : \n");
scanf("%d", &boy1.num);
getchar();
printf("Please Input your name : \n");
gets(boy1.name);
printf("Please choose your gender : M\\F?\n");
gets(boy1.sex);
printf("Please Input your age : \n");
scanf("%d",&boy1.age);
printf("Please Input your score : \n");
scanf("%d",&boy1.score);
boy2 = boy1;
printf("Number:%d\nName:%s\n",boy2.num,boy2.name);
return 0;
}
结构体数组:
数组中的每一个元素都是相同的结构体类型;
一. 结构体数组的定义:(与普通数组的定义相同):
1、:
struct stu
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
};
struct stu boy[6];
2、
struct stu
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
}boy[5];
3、
struct
{
int num;
char name[20];
char sex;
int age;
float score;
struct date birthday;
}boy[5];
二、结构体数组的初始化:
struct stu
{
int num;
char sex;
float score;
}boy[5]={
{101,'m',45},
{101,'m',45},
{101,'m',45},
{101,'m',45},
{101,'m',45}
};
定义时也可不指定元素个数,系统自定:
struct stu boy[]={{……},{……},{……},{……}};
三、结构体数组的引用:
例:
计算学生平均成绩和不及格的人数:
struct stu
{
int num;
float score;
}boy[5]={
{101,45},
{102,62.5},
{103,92.5},
{104,87},
{105,58}
};
void main()
{
int i,c=0;
float ave,s=0;
for(i=0; i<5; i++)
{
s+=boy[i].score;
if(boy[i].score<60) c+=1;
}
ave=s/5;
printf("average=%f\ncount=%d\n",ave,c);
}
结构体指针变量:
指向结构体变量的指针,值为所指向结构体指针的首地址;
定义结构体变量的一般形式:
struct 结构名 *结构体指针变量
struct stu boy *pstu; pstu=&boy;
注意: 1. 结构体指针变量和普通指针一样,赋值前不能使用;
2. 编译系统不给代表结构类型的结构体名分配空间: pstu=&stu; 是错误的
利用结构体指针访问成员:
1. pstu->num ->的优先级高 ++pstu->num 等价于 ++(pstu->num)
2. (*pstu).num 因为.的优先级高,所以(*pstu)必须加括号;
3. stu.num
例:
struct stu
{
int num;
char name[20];
char sex;
float score;
}boy={102,"zhangping",'M',78.5},*pstu;
void main()
{
pstu = &boy;
printf("Sex=%c\tScore=%f\n",boy.sex,boy.score);
printf("Sex=%c\tScore=%f\n",(*pstu).sex,(*pstu).score);
printf("Sex=%c\tScore=%f\n",pstu->sex,pstu->score);
}
指向结构体数组的指针:
struct stu
{
int num;
float score;
}boy[5]={
{101,45},
{102,62.5},
{103,22},
{104,44},
{105,25}
},*ps;
void main()
{
printf("Num:\t\tScore:\t\n"); // 加标题的方法;
for(ps=boy;ps<boy+5;ps++) // 指针循环输出, ps<boy+5 !!终止条件;
printf("%d\t\t%4.1f\t\n",ps->num,ps->score);
}
结构体和函数:
结构体变量的成员作为函数的实参,用法和普通变量做实参一样;
例:
显示学生的基本信息:
struct stu
{
int num;
char name[20];
char sex;
float score;
}student={101,"Zhangping",'M',45};
void main()
{
void list(struct stu student);
list(student);
}
void list(struct stu student) // 直接输出struct stu的成员;
{
printf("Number=%d\t Name=%s\n",student.num,student.name);
}
返回结构体类型数据的函数:
从键盘中读入一个数据:
#include<stdio.h>
#include<stdlib.h>
struct stu
{
unsigned int num;
char name[20];
char sex[2];
int age;
float score;
};
struct stu AddStu();
void PrintStu(struct stu student);
int main()
{
struct stu boy1;
boy1 = AddStu();
PrintStu(boy1);
return 0;
}
struct stu AddStu()
{
struct stu student;
printf("Please Input your student number : \n");
scanf("%d", &student.num);
getchar();
printf("Please Input your name : \n");
gets(student.name);
printf("Please choose your gender : M\\F?\n");
gets(student.sex);
printf("Please Input your age : \n");
scanf("%d",&student.age);
printf("Please Input your score : \n");
scanf("%f",&student.score);
return student;
}
void PrintStu(struct stu student) // 标准输出函数;
{
printf("Number=%d\t Name=%s\n",student.num,student.name);
printf("Sex=%s\t\tScore=%f\n",student.sex,student.score);
}
结构体指针作为函数参数:
struct stu
{
int num;
char name[20];
char sex;
float score;
}student={101,"zhou ping",'M',76};
void main()
{
void list(struct stu *student);
list(&student); // 指针需要取地址;
}
void list(struct stu *p)
{
printf("Number=%d\tName=%s\n",p->num,p->name);
printf("Sex=%c\t\tScore=%f\n",p->sex,p->score);
}
位段结构体:
以位为单位来指定成员所占内存大小;
位段结构体的定义与结构体类型相似;
struct 位段结构体名
{类型符 位域名1:位域长度
类型符 位域名2:位域长度
类型符 位域名3:位域长度
类型符 位域名4:位域长度
…………
}
struct bs
{
int a:8;
int b:2;
int c:6;
}
位域有以下几点说明:
1. 成员类型一般为unsigned或者int ,位域长度为整型常量表达式;
2、 一个位域必须存储在同一个存储单元,不能跨越两个单元;(若一个单元所剩空间不足,该空间不用,直接进入下一个单元);
3. 位域不能跨两个存储单元,因此位域的长度不能大于存储单元的长度;
4. 使用空位域可以使下一个位域从下一个存储单元开始存放;
位域的引用:
位域的引用和结构体成员的引用相同:
位段结构体变量名.位域名 bit.a
例:
void main()
{
struct bs
{
unsigned a:1;
unsigned b:3;
unsigned c:4;
}bit,*pbit;
bit.a=1;
bit.b=7;
bit.c=15;
printf("%d,%d,%d\n",bit.a,bit.b,bit.c);
pbit=&bit;
pbit->a=0;
pbit->b&=3;
pbit->c|=1;
printf("%d,%d,%d\n",pbit->a,pbit->b,pbit->c);
}