C语言—结构体

一、结构体的概念

将不同类型的数据组合成一个有机的整体,以便于引用。
结构体是一种构造数据类型(由一种或多种基本类型或构造类型的数据的集合)

二、 结构体类型定义

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;
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值