目录
结构体类型
- 数组只能将相同类型的数据放在一起,结构体是可以将不同类型的数据放在一起
声明
//结构体模板
struct student
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
int yearBirth;//出生年
int scoreMath;//数学成绩
int scoreEnglish;//英语成绩
int scoreComputer;//计算机
int scoreP;
//int score[4];//等价上面成绩
};
定义结构体变量
1、先定义结构体类型,在定义变量名
struct student//student为标签名
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
};
struct student stu1;//定义变量
2、在定义结构体类型的同时定义变量
struct student
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
int yearBirth;//出生
}stu1;
3、直接定义结构体变量(不指定结构体标签)
struct
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
int yearBirth;//出生年
}stu1;
typedef
- 用typedef给数据类型定义一个别名
- 别名用全部大写
- struct student等价STUDENT
struct student
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
}stu1;
typedef struct student STUDENT;
//或者
typedef struct student
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
}STUDENT;
//或者
typedef struct
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
}STUDENT;//结构体声明
初始化
- 初始化列表成员必须与结构体类型定义的顺序一致
- 没给初始值就默认为0
typedef struct student
{
long studentID;//定义学号
char studentName;//姓名
char studentSex;//性别
int yearBirth;//出生年分
int score[4];//成绩
}STUDENT;
STUDENT stu1={1203,"小王","Man",1991,{72,90,29,28}};//初始化
结构体与数组嵌套
嵌套的结构体
typedef struct data
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
long studentID;//定义学号
char studentName[10];//姓名
char studentSex[10];//性别
DATE yearBirth;//出生年
int score[4];//成绩
}STUDENT;
初始化
- 嵌套的结构体要用花括号表示内容–里面花括号
- 外面花括号—原结构体数组类型
STUDENT stu1={1203,"小王","Man",{1991,5,19},{72,90,29,28}};//初始化
结构体数组
- 前面结构体声明一样
- 数据就用花括号嵌套表示
STUDENT stu1[3]={{1203,"小王","Man",{1991,5,19},{72,90,29,28}},
{13503,"小红","Man",{1991,5,19},{72,90,29,28}},
{1253,"小西南","WOMan",{1983,5,19},{72,90,29,28}}
};
计算结构体内存数
- sizeof(变量或表达式)
- 为满足内存地址要求,在较小的成员加入补位
访问结构体成员
- 通过名字访问结构体成员
- 成员选择运算符(原点运算符)
- 结构体变量名.成员名
- 对于嵌套体成员,必须以级联方式访问
#include <stdio.h>
#include<string.h>
int main()
{
typedef struct data
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
long studentID;//定义学号
char studentName[10];//姓名
char studentSex;//性别
DATE Birth;
int score[4];//成绩
}STUDENT;
STUDENT stu1={12033,"小王",'M',{1991,5,19},{72,90,29,28}};
//访问操作
stu1.studentID=101001;//访问id
strcpy(stu1.studentName,"小");//访问,字符数组要用strcpy函数
stu1.studentSex='M';//若是定义单个字符,直接赋值
stu1.Birth.year=19;//级联方式访问
printf("姓名为%s\n性别是%c\n学号是%d\n",stu1.studentName,stu1.studentSex,stu1.studentID);
}
赋值
- 只能在相同类型的结构体变量之间进行赋值
#include <stdio.h>
int main()
{
int i;
typedef struct data
{
int year;
int month;
int day;
}DATE;
typedef struct student
{
long studentID;//定义学号
char studentName[10];//姓名
char studentSex[10];//性别
DATE yearBirth;//出生年
int score[4];//成绩
}STUDENT;
STUDENT stu1={1203,"小王","Man",{1991,5,19},{72,90,29,28}};
STUDENT stu2;
//赋值
stu2.studentID=stu1.studentID;//赋值
for(i=0;i<4;i++)
{
stu2.score[i]=stu1.score[i];
printf("%d\n",stu2.score[i]);
}
}
取地址操作
STUDENT stu2;
stu1=stu2;
printf("&stu1=%p\n",&stu1 );
printf("&stu2=%p",&stu2);
结构体指针
访问
- 通过成员选择运算符访问
(*pt).studentID=1;
- 通过指向运算符访问:->
pt -> studentID=1;
总体
#include <stdio.h>
int main()
{
typedef struct student
{
long studentID;//定义学号
char studentName[10];//姓名
char studentSex[10];//性别
int score[4];//成绩
}STUDENT;
//定义结构体指针
STUDENT stu1;
STUDENT *pt;
pt = &stu1;//初始化
//STUDENT *pt = &stu1;//与上式等价
//访问
(*pt).studentID=1;
pt -> studentID=1;
stu1.studentID=1;
}
结构体数组
STUDENT stu[30];
STUDENT *pt;
pt=stu;//数组首地址指向指针
//等价
STUDENT *pt=stu;
//等价
STUDENT *pt = &stu[0];
//访问
pt -> studentID;//等价于stu[0].studentID
向函数传递结构体
传递单个成员
向函数传递结构体的完整结构
- 赋值结构体的所有成员
向函数传递结构体的首地址
- 仅复制一个地址值
应用
- 封装函数参数:精简参数个数、函数接口简洁
#include <stdio.h>
typedef struct point//结构体声明
{
int x;
int y;
int z;
}POINT;
void Func(POINT *p);//函数结构体指针定义
int main()
{
POINT position={0,0,0};
printf("%d,%d,%d\n",position.x,position.y,position.z);
Func(&position);//传参
printf("%d,%d,%d\n",position.x,position.y,position.z);
}
void Func(POINT *pt)
{
pt -> x=1;
pt -> y=2;
pt -> z=3;
}
向函数传递结构体完整结构 | 向函数传递结构体的首地址 |
---|---|
用结构体变量做函数参数 | 用结构体数组/结构指针做函数参数 |
复制整个结构体成员内容,一组数据 | 仅复制结构体的首地址,一个数据 |
参数传递直观,开销大,效率低 | 参数传递效率高 |
函数内对结构体内容的修改不影响原来结构体 | 可修改结构体指针所指向的结构体内容 |
枚举类型
- 应用:当某些量仅由有限个整型数据值组成时
- 枚举常量是整型常量
- 增强程序看可读性:定义标志变量
- MON后面常量依次加1
enum weeks ={SUN=7,MON=1,TUE,WED,THU,FRI,SAT}//枚举类型声明
typedef enum weeks ={SUN=7,MON=1,TUE,WED,THU,FRI,SAT} WEEKS;//定义别名
//定义变量
enum weeks today;
WEEKS today;
共用体
声明
- 字节数取决于占空间最多的成员变量
- 同一内存在每一瞬间只能保存一个成员;起作用的成员是最后一次赋值的成员
- 与结构体类似
- 成员最好互斥
union sample
{
short i;
char ch;
float f;
};
//访问
struct sample s;//定义变量
s.i=1;
union sample u={1};//只能对共用体第一个成员进行初始化
应用
- 构造混合的数据类型
typedef union
{
int i;
float f;
}NUMBER;
NUMBER array[100];//既可以存储int型,也可以存储float型
//访问
array[0].i=10;
array[1].f=3.2;
对比
结构体 | 共用体 |
---|---|
关系紧密且逻辑相关的多种不同类型的数据的结集合 | 情形互斥但逻辑相关的多种不同类型的数据的集合 |
可以保存所有成员的值,用sizeof来计算占用内存的总字节数 | 内存重叠存储,每一瞬间只能保存一个成员,最后一次赋值的成员起作用 |
对所有成员初始化 | 只能对第一个成员初始化 |
C程序的内存映像
变量的内存分配方式
- 从静态存储区分配
- 全局变量和静态变量
- 从栈上分配
- 从堆上分配
动态内存分配函数
- void*型指针不指定其指向哪一种类型,可指向任意类型的变量
- 使用时,需强转(Type*)为其他类型
#include<stdlib.h>
void* malloc(unsigned int size);
//向系统申请大小为size的内存块;
void* calloc(unsigned int num,unsigned int size);
//向系统申请num个size大小的内存块
void *realloc(void *p,unsigned int size);
//改变原来分配存储空间的大小
//指针p所指向存储空间的大小改为size个字节
void free(void *p);//释放内存
p=(int*)malloc(n*sizeof(int));//强制转换