IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C语言之指针进阶 -> 正文阅读

[C++知识库]C语言之指针进阶

指针数组<—>数组指针、动态内存、内存四区

  • 指针数组本质就是数组

    • 多个指针的集合
  • 数组指针本质就是指针

  • 二级指针:指向指针的指针

        **p
        **(p+1)
        * (*p+1)
        * (*(p+1))+1)
        * (p[i]+j))
        * (*(p+i)+j))
    

指针数组

  • 指针数组通常用来处理字符串,不需要大小

    //对于指针数组通常是用来处理字符串
    	char* str = "ASEF";		//不需要大小
    	puts(str);
    	char* pStr[3] = { "ERGFDVFD","IMiss","idfSDFef" };
    	//pStr[0] 等效str
    	for (int i = 0; i < 3; i++) 
    	{
    		puts(pStr[i]);
    	}
    	print(pStr,3);
    	char strArray[10] = { "FEFJ" };   //字符串结束表\0 也要算在里面
    	strArray[0] = 'L';
    	puts(strArray);
    
  • 本质就是数组

  • 多个指针的(一级指针)集合

    	int* pArray[3] = { iNum,iNum + 1,iNum + 2 };
    	//pArray[0]  是一个指针变量
    	//pArray[1]  是一个指针变量
    	//pArray[2]  是一个指针变量
    

数组指针

  • 作用单一

  • 常用于表示二维数组

    //通常情况数组指针用来表示二维数组的
    	pArray = array;
    	printf("第一种指针表示二维数组:\n");
    	for (int i = 0; i < 2; i++) 
    	{
    		for (int j = 0; j < 2; j++) 
    		{
    			printf("%d\t", pArray[i][j]);
    		}
    		printf("\n");
    	}
    	printf("第二种指针表示二维数组:\n");
    	for (int i = 0; i < 2; i++)
    	{
    		for (int j = 0; j < 2; j++)
    		{
    			printf("%d\t", *(*(pArray+i)+j));
    		}
    		printf("\n");
    	}
    	printf("第三种指针表示二维数组:\n");
    	for (int i = 0; i < 2; i++)
    	{
    		for (int j = 0; j < 2; j++)
    		{
    			//*(pArray + i) 等效pArray[i]
    			printf("%d\t", *(pArray[i] + j));
    		}
    		printf("\n");
    	}
    
    	printf("第四种指针表示二维数组:\n");
    	for (int i = 0; i < 2; i++)
    	{
    		for (int j = 0; j < 2; j++)
    		{
    			//*(pArray + i) 等效pArray[i]
    			//*(pArray + i) 等效 (pArray+i)[0]  这种很少见
    			// *(*(pArray+i)+j) 让*(pArray+i)等效X
    			//*(X+j)  X[j]
    			printf("%d\t", (*(pArray+i))[j]);
    		}
    		printf("\n");
    	}
    	printArray(array, 2, 2);
    
  • 传参的时候,表示二维数组,所以可以传入数组指针

  • 在这里数组指针是一个指针变量,本质传入的是参数

    void  printArray(int(*pArray)[2], int row, int cols) 
    {
    	printf("数组指针传参打印数组:\n");
    	for (int i = 0; i < row; i++) 
    	{
    		for (int j = 0; j < cols; j++) 
    		{
    			printf("%d\t", pArray[i][j]);
    		}
    		printf("\n");
    	}
    }
    
  • 数组下标有多少列数组下标就是多少

  • 数组指针产生的是一个指针变量,指针变量指向的是一个数组

    	//int(*pArray)[2] = NULL;   这句与下面两句效果一样
    	//括号不能少
    	int(*pArray)[2];
    	pArray = NULL;
    

数组指针解析

  1. 首先把数组指针+1这种操作解析为 数组指针+ sizeof(指针所指向的类型)*偏移量

    	p+n //解析为: p+ sizeof(指针所指向的类型)*n;
    	int(*pArray)[2]  //指针的类型: int(*)[2]  去掉变量名
    	//指针所指向的类型: 去掉变量名和*  : int[2]
    	pArray+sizeof(int[2])*1;
    	//通常情况数组指针用来表示二维数组的
    

指针函数

  • 所有传参方式都是采用赋值的方式

  • 值传递(传普通变量)

    void modify(int a) 
    {
    	a = 100;
    }
    
  • 地址传递(传指针)

    void modifyByPoint(int* a)  
    {
    	*a = 100;
    	//传入是一级指针,修改的是*a这个指针
    	//int* a=&num;
    	//*a=100;   //*a 等效num
    }
    
  • 不能返回局部变量的地址

    int* returnValue() 
    {
    	int temp = 123;
    	return &temp;
    }
    
  • 修改指针指向

    //通过子函数实现修改指针的指向
    int g_num = 10001;
    void modifyPoint(int* p) 
    {
    	p = &g_num;
    }
    void modifyPointCrrect(int** p) 
    {
    	*p = &g_num;
    	//在当前函数中需要修改实参的值(指针的指向的值)
    }
    void printData(int* p) 
    {
    	p = &g_num;   //想要实现这样赋值操作,须要传入二级指针
    }
    

动态内存申请

  • 动态内存申请也叫堆内存申请,动态数组

  • 需要手动申请,手动释放一段内存

  • 从哪里申请的内存,释放的时候就要在哪里释放

  • 同一段内存只能被释放一次

  • 栈内存:每个函数都有自己的一段栈内存,系统自动回收

  • 本质就是函数调用

    • 单纯的内存申请

      void *malloc(size_t size);
      
    • 自动初始化申请

      void* calloc(size_t size,int count);
      
      //malloc(sizeof(int)*3)
      	int* pC = (int*)calloc(3, sizeof(int));
      	assert(pC);
      	for (int i = 0; i < 3; i++) 
      	{
      		printf("%d\t", pC[i]);
      	}
      	printf("\n");
      	free(pC);
      	pC = NULL;
      
    • 重新申请

      void* realloc(void* p,size_t size);	
      //realloc 内存不够再次申请
      	int* pVector = (int*)calloc(3, sizeof(int));
      	assert(pVector);
      	//0,0,0
      	//realloc 重新申请的内存是要打印原来内存
      	pVector = (int *)realloc(pVector, sizeof(int) * 6);
      	assert(pVector);
      	pVector[5] = 100;  //pVector[4]   pVector[3] 
      	for (int i = 0; i < 6; i++) 
      	{
      		printf("%d\t", pVector[i]);
      	}
      	printf("\n");
      	free(pVector);
      	pVector = NULL;
      
    • 内存释放

      void free(void *p);
      

申请单个变量内存

	//强制转换 +malloc
	int* pInt =(int *)malloc(sizeof(int) * 1);
	float* pFloat = (float*)malloc(sizeof(float) * 1);
    double* pDouble = (double*)malloc(sizeof(double) * 1);
//float和double与int的用法一样
	//申请内存可能存在失败
	if (pInt == NULL)
		return;
	printf("%d\n", *pInt);
	*pInt = 100;
	//一个指针只要做了动态内存申请,就可以直接充当变量的用法
	printf("%d\n", *pInt);
	free(pInt);
	pInt = NULL;		//养成这个习惯,避免悬空指针(野指针)
	char* pChar = (char*)malloc(sizeof(char));
	assert(pChar);  //当指针为空时候,调用abort终止程序,并且显示程序中断行数,需要断言头文件 assert.h
	*pChar = 'A';
	putchar(*pChar);
	free(pChar);
	pChar = NULL;

申请多个变量内存(等同于一个数组)

int Num = 0;
	scanf_s("%d", &Num);
	//int array[Num];
	int* pArray = (int*)malloc(sizeof(int) * Num); //等效pArray[Num]这样的数组
  • 直接充当一个数组用即可

    for (int i = 0; i < Num; i++)
    	{
    		pArray[i] = i;
    		//*(pArray+i)=i;
    		printf("%d\t", pArray[i]);
    	}
    	free(pArray);
    	pArray = NULL;
    
  • 长度可以根据用户决定

  • 可以改变数组指向

    char* pStr = (char*)malloc(sizeof(char) * 10);
    	assert(pStr);
    	char str[10] = { "Youngblood" };
    	//strcpy去复制,或者用字符赋值
    	//pStr = "Youngblood";    //这样写会改变指向
    	printf("\n");
    	int i = 0;
    	while (str[i] != '\0') 
    	{
    		pStr[i] = str[i];
    		i++;
    	}
    	pStr[i] = '\0';
    	puts(pStr);
    	pStr++;				//指针指向一段内存更灵活
    	putchar(pStr[0]);
    	//同一段内存,只能被释放一次
    	pStr--;
    	free(pStr);
    	pStr = NULL;
    

动态内存申请二维数组

  • 二级指针申请内存

    void initArray(int **array, int row, int cols)
    {
    	for (int i = 0; i < row; i++) 
    	{
    		for (int j = 0; j < cols; j++) 
    		{
    			array[i][j] = cols * i + j;
    		}
    	}
    }
    
    void printArray(int** array, int row, int cols)
    {
    	for (int i = 0; i < row; i++)
    	{
    		for (int j = 0; j < cols; j++)
    		{
    			printf("%d\t", array[i][j]);
    		}
    		printf("\n");
    	}
    }
    
    int* p1D = (int*)malloc(sizeof(int) * 4);  //p1D[i]都是一个整形变量
    	free(p1D);
    	p1D = NULL;
    	int** pArray=(int**)malloc(sizeof(int*) * 4); //pArray[i] 都是一个一级指针
    	assert(pArray);
    	for (int i = 0; i < 4; i++) 
    	{
    		pArray[i] = (int*)malloc(sizeof(int) * 3);
    	}
    	initArray(pArray, 4, 3);
    	printArray(pArray, 4, 3);
    	for (int i = 0; i < 4; i++) 
    	{
    		free(pArray[i]);
    		pArray[i] = NULL;
    	}
    	free(pArray);
    	pArray = NULL;
    
  • 数组指针申请内存

void initArray1(int array[][3], int row, int cols)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			array[i][j] = cols * i + j;
		}
	}
}
void printArray1(int array[][3], int row, int cols)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			printf("%d\t", array[i][j]);
		}
		printf("\n");
	}
}

int(*p)[3] = NULL;
	//(指针类型)malloc(sizeof(指针所指向类型) * 4);
	p = (int(*)[3])malloc(sizeof(int[3]) * 4);
	initArray1(p, 4, 3);
	printArray1(p, 4, 3);
	free(p);
	p = NULL;

自定义函数申请内存

  • 传参的方式

    void createArrayTwo(int** p,int size) 
    {
    	*p = (int*)malloc(sizeof(int) * size);
    }
    
    int main()
    {
        createArrayTwo(&array, 3);
        for (int i = 0; i < 3; i++)
    	{
    		array[i] = i;
    		printf("%d\t", array[i]);
    	}
    	printf("\n");
    	free(array);
    	array = NULL;
    	return 0;
    }
    
  • 返回值的方式

    • 利用了堆内存不会被系统自动回收特性
    int* createArray(int size) 
    {
    	int* p = (int*)malloc(sizeof(int) * size);
    	//有效利用了堆内存不会被系统自动回收特性
    	return p;
    }
    
    int main()
    {
        int* array = createArray(3);
        //使用数组 也就是使用申请内存
    	for (int i = 0; i < 3; i++) 
    	{
    		array[i] = i;
    		printf("%d\t", array[i]);
    	}
    	printf("\n");
    	free(array);
    	array = NULL;
        return 0;
    }
    

内存四区

  • 代码区

    • 存放程序的二进制代码
  • 栈区

    • 存放局部变量,子函数参数等,内存系统自动回收
    • 每一个函数的栈区都是不一样,函数名就是函数占用的地址
  • 堆区

    • 手动申请手动申请的
    • malloc 、realloc、 calloc 申请内存都是堆区
    • 堆区需要 free释放
  • 全局区(静态区)

    • 常量
    • 静态变量
    • 全局变量

    栈区----->全局区

    #include <stdio.h>
    
    int Max(int a, int b) 
    {
    	return a > b ? a : b;
    }
    int Min(int a, int b)
    {
    	return a > b ? b : a;
    }
    
    int main() 
    {
    	int a = 1;
    	int b = 2;
    	int i = 0;
    	printf("%d\t%d\t%d\t", i++, i++, i++);  //打印的是2,1,0;从右往左入栈
    	int max = Max(1, 2);
    	int min = Min(1, 2);
    	char* str = "ILoiy";
    	//str[0] = 'A';  错误代码
    	int* p = NULL;
    	//*p = 100;   错误代码
    	//指针充当变量
    	//用变量的地址
    	int num = 0;
    	p = &num;
    	*p = 100;
    	//堆内存初始化
    	p = (int*)malloc(sizeof(int));
    	*p = 100;
    	printf("%d\n", *p);
    	free(p);
    	p = NULL;
    	char* pstr[3] = { "Point","Feasible","d" };
    	pstr[0] = "Hidden";
    	char* ppstr = "Il";   //本质是存的是常量的字符串的地址的,并不是直接存的字符串
    	ppstr = "Kedah";   //可以修改指向,但是不能修改莫一个常量区字符串的值 
    	puts(ppstr);
    	//长度只对数组又影响
    	return 0;
    }
    
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-10-08 20:22:12  更:2022-10-08 20:25:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 4:03:33-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码