文章目录
一、结构体的概念
将不同类型的数据组合成一个有机的整体,以便于引用。
结构体是一种构造数据类型(由一种或多种基本类型或构造类型的数据的集合)
二、 结构体类型定义
2.1 结构体类型的定义
(1)struct 结构体类型名{
成员列表
};
例
struct stu{
int num;
char name[20];
char sex;
};
//有了结构体类型以后,就可以用类型定义变量
struct lucy,bob,helen; //定义了三个struct stu类型的变量
每个变量里都有三个成员,分别是num,name,sex
暂时可以认为结构体变量的大小是它所有成员的和
(2)struct 结构体类型名{
成员列表
}结构体变量1,变量2;
struct stu{
int num;
char name[20];
char sex;
}lucy,bob,helen;
(3)在定义结构体类型的时候,没有结构体类型名,顺便定义结构体变量,因为没有类型名,所以以后不能再定义相关类型的数据了
struct {
成员列表
}结构体变量1,变量2;
struct{
int num;
char name[20];
char sex;
}lucy,bob,helen;
(4)typedef
typedef struct stu{
int num;
char name[20];
char sex;
}STU;
STU就相当于struct stu
STU lucy就等价于struct stu lucy
三、结构体变量的定义初始化
3.1结构体变量的初始化
#include <stdio.h>
struct stu{
int num;
char name[20];
char sex;
};
int main(){
struct stu Lucy={101,"lucy",'f'};
return 0;
}
3.2 结构体变量的使用
(1)赋初值
#include <stdio.h>
#include <string.h>
struct stu{
int num;
char name[20];
char sex;
char *addr;
};
int main(){
struct stu Lucy;
Lucy.num=100;
//Lucy.name="lucy"; // 错误,name是数组名即数组的首地址,不能用等号给常量赋值
strcpy(Lucy.name,"lucy");
printf("%d %s\n",Lucy.num,Lucy.name);
//strcpy(Lucy.addr,"beijing"); //错误,bob.addr是个野指针
bob.addr="beijing";
return 0;
}
(2)结构体成员的多级引用
#include <stdio.h>
#include <string.h>
struct date{
int year;
int month;
int day;
};
struct stu{
int num;
char name[20];
char sex;
struct date birth;
};
int main(){
struct stu boy={01,"bob",'m'};
boy.birth.year=2001;
boy.birth.month=1;
boy.birth.day=12;
return 0;
}
(3)相同类型的结构体可以相互赋值
#include <stdio.h>
struct stu{
int num;
char name[20];
char sex;
};
int main(){
struct stu Lucy={101,"lucy",'f'};
struct stu bob;
bob=Lucy;
return 0;
}
四、结构体数组
结构体数组就是个数组,由若干个相同类型的结构体变量构成的集合
#include <stdio.h>
#include <string.h>
struct stu{
int num;
char name[20];
char sex;
}edu[3];//定义了一个struct stu类型的结构体数组
int main(){
edu[0].num=100;
strcpy(edu[0].name,"carrie");
printf("%d %s\n",edu[0].num,edu[0].name);
return 0;
}
五、结构体指针
结构体指针即结构体的地址,结构体变量存放在内存中,也有起始地址
我们定义一个变量来存放这个地址,那么这个变量就是结构体指针变量
结构体指针变量也是个指针,在32位环境下,指针变量也占4个字节,存放一个地址编号
1、结构体指针变量的定义方法:
struct 结构体类型名 *结构体指针变量名
struct stu * p; //定义了一个struct stu *类型的指针变量
p是变量名,占了四个字节
例: struct stu boy;
p=&boy;
访问结构体变量的成员的方法:
boy.num=101
(*p).num=101 //*p相当于p指向的变量boy
p->num=101 //指针->成员名
例:传结构体变量的地址
#include <stdio.h>
#include <string.h>
typedef struct stu{
int num;
char name[20];
double score;
}stu;
void input(stu* girl){
girl->num=101;
strcpy((*girl).name,"lucy"); //strcpy(girl->name,"lucy");
girl->score=99.9;
}
int main(){
stu girl;
input(&girl);
printf("num=%d name=%s score=%.2f\n",girl.num,girl.name,girl.score);
return 0;
}
例:传结构体数组的地址
结构体数组,是由若干个相同类型的结构体变量构成的集合。存放在内存里,也有起始地址,其实就是第0个结构体变量的地址
#include <stdio.h>
typedef struct stu{
int num;
char name[20];
float score;
}STU;
void input(STU* edu,int n){
int i;
for(i=0;i<2;i++){
printf("请输入第%d个学生的成绩:\n",i+1);
printf("num=");
scanf("%d",&edu[i].num);
printf("name=");
scanf("%s",edu[i].name);
printf("score=");
scanf("%f",&edu[i].score);
}
}
void output(STU* edu,int n){
int i;
for(i=0;i<n;i++){
printf("num=%d name=%s score=%.2f",edu[i].num,edu[i].name,edu[i].score);
printf("\n");
}
}
int main(){
STU edu[2];
input(edu,2);
output(edu,2);
return 0;
}
注意:结构体变量的地址编号和结构体第一个成员的地址编号相同,但指针的类型不同
#include <stdio.h>
typedef struct stu{
int num;
char name[20];
float score;
}STU;
int main(){
STU edu;
//这两个指针指向同一个地方,但是指针类型是不一样的
printf("&edu=%p\n",&edu); //STU*指针
printf("&(edu.num)=%p\n",&(edu.num));//int*型指针
return 0;
}
六、结构体内存分配
规则1:以多少个字节为单位开辟内存
给结构体变量分配内存的时候,会去结构体变量中找基本类型的成员
哪个基本类型的成员占字节数多,就以它大小为单位开辟内存
(1)成员中只有char型数据,以1字节为单位开辟内存
(2)成员中出现了short int类型数据,没有更大字节数的基本类型数据,以两字节为单位开辟内存
(3)成员中出现了int float类型数据,没有更大字节数的基本类型数据,以四字节为单位开辟内存
(4)出现了double类型数据,在VC6.0和Visual Studio中,以八字节为单位开辟内存
注意:
如果在结构体中出现了数组,数组可以看成是多个变量的集合
如果出现指针的话,没有占字节数更大类型的,以四字节为单位开辟内存
规则2:字节对齐(未了解)
七、共用体
1、定义:共用体和结构体类似,也是一种构造类型的数据结构
定义共用体类型的方法和结构体非常相似,把struct改成union就可以了
在进行某些算法时,需要使用几种不同类型的变量存储到同一段内存单元中,几个变量所使用空间相互重叠(共用一块内存),这种几个不同的变量共同占用一段内存的结构,在c语言中,被称作“共用体”类型结构
共用体的大小是其占内存长度最大的成员的大小
typedef union data{
short int i;
char ch;
float f;
}DATA;
DATA temp2; //共用体temp2占了4个字节,即i,ch,f共用四个字节
2、特点
(1)同一内存段可以用来存放几种不同类型的成员,但每一瞬间只有一种起作用
(2)共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后,原有的成员值会被覆盖
(3)共用体变量的地址和它的各成员的地址都是同一地址
(4)共用体变量的初始化 union data a={1,2,3};
初始化共用体只能为第一个成员赋值,不能给所有成员赋值
八、枚举
将变量的值一一列举出来,变量的值只限于列举出来的值的范围内
枚举类型也是个构造类型的
使用枚举的时候,得先定义枚举类型,再定义枚举变量
例:定义枚举类型week
enum week{
mon,tue,wed,thu,fri,sat,sun
};
enum week workday,weekday; //枚举变量
//workday与weekday只能取sun...sat中的一个
#include <stdio.h>
/*
(1)枚举元素本身由系统定义了一个表示序号的数值,默认是由0开始顺序定义为0,1,2
如在week中,mon的值为0,tue的值为1....
(2)可以改变枚举值的默认值
enum week{
mon=3,tue,wed,thu,fri,sat,sun
};
mom=3,tue=4
(3)在程序中不能再次对枚举元素赋值,因为枚举元素是常量
(4)枚举元素也可以用来判断比较 if(workday==mon);
*/
enum week{
mon,tue,wed,thu,fri,sat,sun //枚举元素默认都是常量
};
int main(){
enum week workday;
workday=mon;
printf("workday=%d\n",workday);
//tue=8; //这是错误的,tue是常量,不能在程序中用赋值语句再对它赋值
//workday=abc; //枚举元素中没有abc
//workday=100; //虽然可以,但是不要这么操作,一般都用枚举元素给枚举变量赋值
return 0;
}
例:枚举类型的应用
题目:口袋中有红黄蓝白黑五种颜色的球若干个。每次从口袋中先后取出三个球,问得到三种不同颜色的球的可能取法,输出每种排列的情况。
#include <stdio.h>
enum color{red,yellow,bule,white,black};
int main(){
enum color i,j,k,pri;
int count=0,loop;
for(i=red;i<=black;i++){
for(j=red;j<=black;j++){
if(i!=j){
for(k=red;k<=black;k++){
if((i!=k)&&(j!=k)){
count++;
printf("%-4d",count);
for(loop=1;loop<=3;loop++){
switch(loop)
{
case 1:pri=i;break;
case 2:pri=j;break;
case 3:pri=k;break;
default:break;
}
switch(pri)
{
case red : printf("%-10s","red");break;
case yellow:printf("%-10s","yellow");break;
case bule:printf("%-10s","blue");break;
case white:printf("%-10s","white");break;
case black:printf("%-10s","black");break;
default:break;
}
}
printf("\n");
}
}
}
}
}
printf("一共有%d种可能",count);
return 0;
}