一周学完c系列 第6天笔记
本帖最后由 代号3 于 2018-4-30 15:09 编辑结构体和联合体
如何自定义数据类型
堆空间
如何自己获得动态的内存空间
指针的高级使用
如何保存不同类型的数据的地址
eg:保存变量的指针
保存数组的指针 指针数组 新类型
保存指针的指针
结构体和联合体
结构体
把具有内在联系的多个不同类型的数据结合成一个整体,使它们关联起来
定义
直接定义 初级形式
struct
{
类型名1 成员名1;
类型名2 成员名2;
}结构体变量名={初始化元素1,初始化元素2,~,初始化元素n};
先定义结构体类型,再定以结构体变量简便方式
struct MyStruct
{
类型名1 成员名1;
类型名2 成员名2;
};
MyStruct stc1;
常用
给结构体起名的同时定义一个变量 中间模式 不常用
strct 结构体名
{
类型名1 成员名1;
类型名2 成员名2;
}变量名;
此时变量即为结构体类型变量
嵌套
结构体体中的成员可以是其他结构体类型
不能嵌套自己本身,但可以嵌套自己类型的指针 ?能否通过指针嵌套自身 //可以
大小
结构体类型只说明该类型成员的组成情况,编译系统并未给它分配空间 只有定义属于结构体类型的变量时,系统才会分配存储空间给该变量
占用内存空间是其成员所占内存之和
自动补满4字节 (编译系统决定) ?题目中按什么规则计数 // 按照结构体最大的类型内存补齐 补齐4或8 没有则不进行补齐
char name
char sex
int age
float height
内存 20+4+4+4 32 补齐 字符数组开辟
初始化
一一对应
全部初始化
定义时初始化,按顺序将结构体变量各成员的初值按顺序放在{}内,并用逗号隔开。
部分初始化
只给部分成员赋初值;
字段引用
‘.’成员运算符
可以连续使用成员运算符访问到自己想要的那一级 就近原则
输出结构体字段的值 根据结构体字段本身的数据类型来输出 参数引用问题
使用结构体字段类比使用普通的变量 等价使用
若结构体字段为结构体类型时 需要使用.运算符访问到所需要的字段
联合体
union 联合体变量名变量名
{
类型名 成员名;
};
union 变量名;
常用定义方式
区别 结构体中的成员 内存独立 联合体中的成员共用一块内存空间
最大的字段内存大小决定联合体内存大小
公用内存空间首地址 取值时由字段类型决定所取
通过指针修改内存时 每次修改长度由指针类型确定
联合体可以作为结构体成员,结构体也可以作为结构体成员
类型定义
允许用户重定义 所有的数据类型
typedef 类型名 标识符;
原始类型名 新的类型名
定义指针的时候习惯在变量名前边加p
?含数组的结构体在循环赋值时的内存量与实际名称的对应关系//通过同步改变printf 引入变量显示即可
指针结构体访问不可以使用.运算符 需要使用->访问结构体成员
堆空间
动态空间 堆 申请出的空间成为堆空间 1~2G左右
局部变量 栈 小 2m左右
malloc 申请堆空间关键字
申请单个元素的堆空间
int * pNum=(int*)malloc(sizeof(int));
可以像使用普通变量一样使用堆空间
申请多个元素的堆空间
char* pStr=(char*)malloc(sizeof(char));
memset(pStr,0,100*sizeof(char));初始化100个pStr堆空间
申请结构体类型的堆空间
Per* pStrobj=NULL;
pStcObj =
(PERSON*)malloc(10 * sizeof( PERSON ));
将结构体变量的内存都填充为0
memset( pStcObj , 0 , sizeof( PERSON ) );
当成数组使用 使用
本质是连续的内存空间
free 释放
定义宏
#difine FREE(p)free(p)
定义指针变量
申请内存空间 将首地址赋值给指针变量通过指针变量访问这片内存
用完释放此空间
使用时注意
申请时可能失败 需要检查
刚分配的动态内存初始值不确定 使用前需要初始化
不要越界访问
释放时注意
只能释放堆空间 不能对静态内存区使用free 可以对空指针NULL应用free
不能对同一个指针 地址连续两次进行free操作
对一个指针应用free后 值不会改变 但它指向了一个无效的内存区 称为悬空指针 及时把指针置为NULL 防止重复释放
或错误的使用已释放空间。
野指针 未进行初始化的指针,指向随机区域
宁可置空指针也防止悬空指针野指针出现
没有及时释放某块动态内存,并且将指向它的指针指向别处,会造成“内存泄露”
内存初始化函数
memset
void *memset
(
void *dest, 目标缓存
int c, 初始化信息
size_t count 初始化大小
);
内存拷贝函数
memcpy
void *memcpy
(
void *dest,
const void *src,
size_t n
);
c的内存结构
静态数据区 全局变量 用 static修饰的局部变量
常量数据区 字符串常量
代码区 程序指令 大部分字面常量
栈区 大部分函数的形参和局部变量 一个函数可用1~20m左右 局部变量生存期
堆区 程序中动态分配的内存
CPU寄存器组 一部分函数的形参和局部变量
生存周期
静态生存期
全局变量
定义static存储类型的局部变量
自动生存期
局部变量
函数形参
动态生存期
堆空间的申请释放
指针的算术运算
可用运算符 + - ++ -- += -=
指针+整数
表示指针偏移整数个元素
指针-指针(没有+)
两个指针属于同一个类型
得到一个整型 两个指针之间的数据的个数 并非两个地址的差值
?结构体 中~~ 有不同的数据类型的时候
-= 不可以用 得到的数据是整型数据 乱码输出
指针与一维数组
数组名是数组类型的常量
数组名,数组的起始地址 可以隐式转换为数组做存储元素的指针类型
sizeof(数组名(表示整个数组 没有退化)) 其他时候数组名大部分表示数组首地址或者数组第一个元素的地址
*(a+2) *&a *p+2 *&p 表示同一个数据
a+2,&a,p+2,&p表示同一个地址
指针与二维数组
数组名 数组的起始地址 可以隐式转换
二维数组中的每一个元素都是一维数组 一维数组类型定义如下
eg:int (*p); 符号优先级解释 数组指针 (新的类型)(对其进行取内容时,取出的是一个数组
二维数组的列数 对取出的一维数组再取内容可行)
行号*列的个数+列
一维数组指针类型 (注意所指向数组的长度)
对一维数组指针解引用会降维,变成一级指针
对一维数组指针使用下表运算符也会降维,变成一级指针
对一维数组指针+1,会得到下一排的起始地址,类型还是数组指针
对一维数组名取地址,会变成二维数组指针,数值不变
页:
[1]