c语言学习笔记 内存四区和多级指针

一.数组作为参数

  1. 形参中的数组,编译器会把他当作指针处理。
  2. 把数组的内存首地址和数组的有效长度传给调用函数。
  3. 形参写在函数上括号,写在函数内,只不过是具有对外的属性。

二.内存四区模型

  1. 数组数据类型(定义一个数组类型 数组指针 数组类型和数组指针类型的关系)
    b &b的数据类型不一样
    b:数组首元素地址
    &b:整个数组地址
    2.数据别名 typedef
    3.数据类型封装 void* 可以指向任何数据类型
    malloc返回值数据是void*,void*做右值赋给其他类型指针需要强制类型转换
  2. 函数也是一种数据类型
  3. 变量 通过变量往内存中写数据 变量在程序区
  4. 内存四区模型图

流程说明
1、操作系统把物理硬盘代码load到内存
2、操作系统把c代码分成四个区
3、操作系统找到main函数入口执行

1.指针指向谁,就把谁的地址赋给指针。
2.指针变量和他指向的内存空间变量是不同的概念
  1. main可以在栈分配内存,在堆分配内存,在全局区分配内存,可以被其他函数使用
  2. 在fa,fb生成的内存可以被main使用?
    fa在栈上分配的内存,不能被fa,main使用
    fbmalloc的内存(堆),可以被使用
    fb中在全局区分配的内存,是可以被fa main使用

三.指针
1.指针做函数参数,形参有多级指针,只需分配4个字节内存。当使用内存时,才关心指向的内存时一维,二维。
2.间接赋值的条件
条件一定义了两个变量
条件二 建立关联
条件三 *p

四.字符串
1.c语言的字符串是以0结尾
2.在c语言中没有字符串类型,通过字符数组模拟字符串
3.字符串的内存分配 堆 栈 全局区
4.strlen长度不包括0,sizeof 内存块大小

五.[ ]与*本质一样,都是操作内存
数组的首地址是只读常量,是一个常量指针,不可更改。

六.一级指针的操作模型
strcpy(a,b) 把b内存的数考到a的内存

七.项目开发字符串模型
1.strstr -whiledowhile
//char *p=”abcd1113333abcd”;求字符串中abcd出现的次数
// strstr();//查找出现第一次的位置
demo
int main()
{ int ncount;
char *p=”abcd1113333abcdqqqq3333abcd”;//p初始化

do
{
p=strstr(p,”abcd”);从指针位置开始,查找abcd字符串,返回abcd第一次出现的位置
if(p!=NULL)
{
ncount++;
p=p+strlen(“abcd”);//指针后移
}
}
while( *p!=’\0’) ;

	printf(“%d”,ncount)

};

int count(char* p,char* b,int* a)
{
char *temp =p;
while(temp=strstr(temp,b) )
{
*a=*a+1;
temp=temp+strlen(“abcd”);

if(*temp==’\0’)
{
break;
return a;
}
}
}
不能轻易改变形参的值,再定义一个变量接替,返回值通过指针返回
八:1.通过递归的方式,逆向打印
理解递归,参数的入栈模型,函数的嵌套调用返回流程

2递归和全局变量(把逆序的结果存入全局变量)
3. 递归和非全局变量,使用指针做函数参数

九:一级指针模型易错分析(重点)

  1. 判断指针是否为空,并不是指针指向的内存值为0;
  2. malloc的内存,注意释放时的地址
  3. const修饰符
    const int a代表只读,但是可以通过指针修改
    const char *c 指针指向的数据不能修改 但是指针本身可以修改
    char * const d 指针变量不能修改,但是指针指向的内存空间可以改变

十:二级指针做输入输出模型
二级指针的输入,就是一级指针取地址,二级指针指向的内存是地址(一级指针的值);主调用函数分配内存

  1. 二级指针做输入第一种模型 指针数组
    char *myarray[10]
    数组中的每个元素都是指针,指针数组,数组排序改变的是指针的指向

  2. 二级指针做输入第二种模型 char myarray[10][30]. 二维数组
    myarray [i] 是myarray [i] [j] 的地址 所以他是一个地址的数组,就是指针数组,也是二级指针
    与第一种指针的步长不一样,步长为一行(30)指针指向内存空间的数据类型不一样 交换的是内存块

  3. 二级指针做输入第三种模型
    自己malloc内存 char p =(char)malloc( sizeof(char*) * num) 指针数组 一维
    p[i]=(char*) malloc( sizeof(char) * 100)内存数组 细分内存
    把内存空间地址给指针就是指针指向内存
    char **p=(char **)malloc(10sizeof(char));
    if(p==NULL)
    for (i=0;i<=10,i++)
    {
    p[i]=(char )malloc(sizeof(char30));//指针可以加【】往后移
    if(p[i]=NULL)
    }

  4. 多级指针避免野指针
    使用多出口,判断是哪一次分配出错,进行不同的free操作
    先释放一级指针p[i],再释放二级指针p

十一.数组类型

  1. 元素类型角度 数组是相同类型的变量的有序集合
  2. 内存角度 连续的一大片内存空间
  3. memset (c,0,sizeof©)//重置内存块
  4. 一维数组规定
    数组首元素的地址 和数组的地址 //c是数组首元素的地址,&c是整个数组的地址,步长不一样
  5. 数组名代表数组首元素的地址,它是个常量。一定义数组就分配内存,内存就固定了
  6. 数组首元素地址和整个数组地址相同
  7. 怎么表达int a[10]这个类型?类型本质 固定大小内存块的别名
  8. typedef int(MYINT5)[5] 定义了一个数据变量MYINT5 array。int array [5]

十二,数组类型指针 指向数组的指针
1.通过数组类型定义数组指针
typedef int(MYINT5)[5] MYINT5 * pointer 指向数组
2.声明一个数组指针类型
typedef int(*MYINT)[5]. MYINT5 mypoint
4.直接定义数组指针
int (*pmyarray)[5] 指向数组的指针。数组指针变量

十三.多维数组的本质
1.a[3][5] a多维数组名的本质就是一个数组指针。 a+1往后跳了20个字节(一行的5列 每个4个字节)
定义一个指向数组的指针变量
int (*pmyarray)[5] //告诉编译器给我分配4个字节的内存
pmyarray = a;
a+i代表整个第i行地址 二级指针 二级指针
*(a+i)代表一级指针。第i行首元素地址 只不过第一行整个行的地址和第一行首元素地址重叠
(a+i)+ j相当于&a[i][j]
[ ]相当于

2.多维数组做参数退化过程 退化为一个数组指针

十四.指针数组应用场景

  1. 菜单
  2. 命令行
  3. 指针数组的自我结束

十五.结构体

  1. 定义一个结构体struct teacher{
    char name[ 64];
    int age;
    id;
    };
    这是定义了一个数据类型
    struct teacher t1;

  2. typedef struct teacher{
    char name[ 64];
    int age;
    id;
    } teacher;
    teacher t1;

  3. 初始化变量
    teacher t1={“aa”,31,11};定义变量,直接初始化
    通过指针的方式操作内存空间
    teacher *p =NULL;定义结构体指针
    p=&t1;
    p->age;

  4. 结构体嵌入一级指针和二级指针

  5. 结构体的深copy和浅copy
    浅拷贝:只会拷贝指针地址 编译器的=只会吧指针变量的值拷贝,不会执行内存空间的拷贝
    如果想执行深copy,需要显示分配内存
    6.结构体的高级话题
    偏移量 一旦结构体定义下来,结构体内成员的内存布局就定下来了
    可以通过成员的地址求大的结构体内存
    两个指针不能相减 强制转换int再减

十六.文件操作

  1. 文件分类
    记录文件
    流式文件:由一个个字符(字节)组成

按数据的组织形式
文本文件 ascii
二进制文件
2. 文件api分类
fgetc fputc 按照字符读写文件
fputs fgets 按照行读写文件(配置文件)
fread fwirte 按照块读写文件 (大数据块迁移 )
3. 配置文件读写库的实践

  1. 大数据文件的加密和解密
    加密基本原理:
    对称加密 加密的密钥和解密的一样 运算速度快 加密强度适合做大数据 强度弱

非对称加密 加密的密钥和解密的不一样 运算速度慢 强度大
明文 秘文 密钥

十七.动态库

  1. .lib 资源描述文件 描述dll
  2. dll 动态库(函数二进制码集合,里面有函数的函数体),动态库是有规范的(Linux win)
  3. lib和dll放到到.c的平级,lib放到外部依赖项。
  4. 自己写的dll文件,在debug里找到lib dll
  5. dll文件在函数前加关键字使得函数可以被调用
  6. f11进入动态库的代码
  7. 句柄

头文件做的是连接作用

动态库与静态库
让其他程序来使用
1. 动态库
.dll 逻辑代码 加载 运行时加载到代码中 程序本身(exe)
dll是个应用程序 必须由exe来运行
#pragma comment(lib,”***.lib”)

2.静态库
.lib 逻辑代码。 在编译完成之后就已经存在程序之中 程序本身会变大

你可能感兴趣的:(指针,字符串,c语言)