C语言指针与数组

指针操作数组

  • 指针操作一维数组
//int array[3]
//数组名: 代表了这段内存首地址  --->指针
//&array[0]
//正常操作: 直接存储数组的首地址
//直接把指针当作数组名就可以了
//非正常操作:指向其他元素开始操作数组

#include <stdio.h>
int main() 
{
	int array[3] = { 1,2,3 };
	printf("%p\n", array);
	printf("%p\n", &array[0]);
	int* p = array;
	for (int i = 0; i < 3; i++) 
	{
		//printf("%d\t", p[i]);  //--->这种方式使用不会错误
		printf("%d\t", *(p + i));
		//*(p+i) 等效p[i];
	}
	printf("\n");
	//array = array + 3;  不能修改
	//array-->&array[0]
	//array+3-->&array[3];
	for (p = array; p < array + 3; p++) 
	{
		printf("%d\t", *p);
		//*p等效p[0]  取当前地址对应内存中值
	}
	printf("\n");

	int test[3] = { 1,2,3 };
	int* pT = &test[2];
	printf("%d\n", pT[0]);   //指针操作数组,用数组用法,[0]下表不一定是第0个元素
	printf("%d\n", pT[-1]);
	printf("%d\n", pT[1]);	 //未知量  -858993460
	return 0;
}
//一级指针操作字符串
	char str[] = "ILoveyou";
	char* pstr = str + 3;
	puts(pstr);
	//[]操作等效取*运算
	putchar(pstr[0]);   //pstr[0] 等效*pstr操作,等效取当前地址下面值
	//*pstr 等效*(str+3) 等效 str[3];
	char* lastchar = str + 8;
	putchar(lastchar[0]);
	pstr = str;
	printf("\n");
	puts(pstr);
  • 指针操作二维数组
//二维数组基础知识
//数组名:指针数组的指针
//行地址:数组名[i];
//一级指针操作二维数组 (二维数组在内存连续的)
//数组指针操作二维数组
#include <stdio.h>
//void printArray2D(int p[][3], int cols, int row) 
void printArray2D(int(*p)[3], int cols, int row) 
{
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", p[i][j]);   //自己写代码这样就行,怎么方便怎么来
		}
		printf("\n");
	}
}

int main()
{
	int array[2][3] = { 1,2,3,4,5,6 };
	int* p = &array[0][0];
	//warning C4047: “=”:“int *”与“int (*)[3]”的间接级别不同
	//p = array;
	printf("%p\n", array);
	printf("%p\n", &array[0][0]);
	printf("%p\n", array[0]);

	printf("%p\n", array + 1);   //12/4=3
	printf("%p\n", p + 1);		 //4
	printf("%p\n", array[0] + 1);
	//char* pC = &array[0][0];
	//int* pI = &array[0][0];
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", *(p + j + i * 3));
			//j+i*3 把坐标转为第几个元素
			//p+n 等下偏移
		}
		printf("\n");
	}

	int(*pArray)[3] = NULL;    //括号必须要有,列数和表示的数组的列数必须相同
	//先算() ,他是一个子指针, 数组指针  指向数组的指针
	//联想整形指针,指向整数
	pArray = array;
	//直接当作数组名去名
	printf("-------------------------------\n");
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", pArray[i][j]);   //自己写代码这样就行,怎么方便怎么来
		}
		printf("\n");
	}
	printf("-------------------------------\n");
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("%d\t", *(*(pArray + i) + j));
			//一维数组:p[i] 等效 *(p+i)
			//printf("%d\t", *(pArray[i] + j));
			//取* 等效数组下表运算 *(pArray+i)  (pArray+i)[0]
			//printf("%d\t", *((pArray + i)[0] + j));
			//printf("%d\t", ((pArray + i)[0] + j)[0]);
			//printf("%d\t", (pArray[i] + j)[0]);
			//看到会读就OK
		}
		printf("\n");
	}
	printf("-------------------------------\n");
	printArray2D(array, 2, 3);

	//存储多个字符串--->指针数组 多个指针变量
	//整形数组: 多个整形变量
	char* pstr[3] = { "Iloveyou","IMiss","IiIIII" };  //每一行上面字符串可以不相同,并且不浪费
	//int array[3]  array[0] array[1] array[2]
	//pstr[0] pstr[1] pstr[2]; 分别存储的是每个字符串首地址
	for (int i = 0; i < 3; i++) 
	{
		puts(pstr[i]);
	}
	//字符串二维数组也可以存储多个字符串? 列数相同 会导致浪费,多余内存
	return 0;
}

二级指针

//int** p=NULL;
//int*** pp=NULL;
#include <stdio.h>
int main() 
{
	int a = 1;
	int* p = &a;		//一级指针变量存储的普通变量的地址
	int** pp=&p;		//二级指针变量存储一级指针变量地址
	//*地址 --->得到当前地址对应内存中的值
	printf("%d\t%d\n", *p, p[0]);
	printf("%d\t%d\n", **pp, pp[0][0]);
	int array[2][3] = { 1,2,3,4,5,6 };
	//一级指针算偏移
	//数组指针做遍历
	// warning C4047: “=”:“int **”与“int (*)[3]”的间接级别不同
	// 所有这种提醒麻烦大家当作错误处理 C++当作是错误的
	//pp = array;
	//for (int i = 0; i < 2; i++) 
	//{
	//	for (int j = 0; j < 3; j++) 
	//	{
	//		printf("%d\n", pp[i][j]);
	//	}
	//	printf("\n");
	//}
	return 0;
}

动态内存申请

  • 动态内存申请的函数
//No.1 断言
#include <assert.h>
assert(p);		//p等于 触发断点,中断程序 断言

#include <malloc.h>
//#include <stdlib.h>
//No.2 malloc  动态内存,不做初始化
void*  malloc(size_t _Size);  //size:申请内存的总字节数
//No.3 calloc  动态内存申请,会初始化为0
void*  calloc( size_t _Count,size_t _Size); //有几个数据:count,每个数据占用的字节数:size
//No.4 realloc  内存重新申请,保留原数据
void*  realloc(void*  _Block,size_t _Size); //原指针,重新申请的内存大小
//No.5 释放内存函数
void  free(void* _Block);
//__cdecl 调用准则,限定参数传参顺序(入栈顺序)--->了解一下
//_In_ 参数类型修饰 传入
//_out_ 传出参数
//size_t  unsigned int
//void* 使用前必须强制类型转换

 

#include <stdio.h>
#include <assert.h>
#include <malloc.h>
int main() 
{
	//No.1 malloc使用方式
	int* p = NULL;
	//assert(p);		//p等于 触发断点,中断程序 断言
	//1.一级指针动态申请内存成为一维数组
	p = (int*)malloc(sizeof(int) * 3);	// int p[3];
	assert(p);
	//等效:
	//if (p == NULL)
	//	return 0;
	//(指针类型)malloc(sizeof(指针所指向的类型)*个数);
	//int* p 
	//指针的类型: 去掉变量名: int*
	//指针所指向类型: 去掉变量名和* :int (操作的数据类型)
	for (int i = 0; i < 3; i++) 
	{
		p[i] = i;
		printf("%d\t", p[i]);
	}
	printf("\n");
	//数组经典错误
	int num = 0;
	scanf_s("%d", &num);
	//int array[num];  //错误 ,定义数组长度必须是常量 
	//C语言可以不写,建议写上,证明你学过void*
	int* pMeory = (int*)malloc(sizeof(int) * num);  //理解为一个数组
	assert(pMeory);
	//什么时候释放,当你不需要他的时候释放
	//注意点: 从那里申请的一定要从那里释放
	pMeory++;    
	//.....
	//无效堆栈指针
	pMeory--;
	free(pMeory);
	pMeory = NULL;			//防止野指针
	free(p);
	p = NULL;				//防止野指针
	//直到整个程序关掉,内存才会操作系统回收
	//No.2 calloc使用方式
	int* pc = (int*)calloc(3, sizeof(int));		//3也可以变量
	assert(pc);
	for (int i = 0; i < 3; i++) 
	{
		printf("%d\t", pc[i]);
	}
	printf("\n");
	int* pr = realloc(pc, sizeof(int) * 6);		//sizeof(int) * 6一定要比原来大小要大
	assert(pr);
	for (int i = 0; i < 6; i++) 
	{
		printf("%d\n", pr[i]);
	}
	//free(pc);
	//pc = NULL;
	free(pr);
	//free(pr);  同一段内存不能被重复释放
	pr = NULL;
	//指针充当变量只有两种途径
	//1.指向变量
	int a = 1;
	int* pa = &a;
	*pa = 1234;
	int result = (*pa) * 3;
	//2.动态内存申请
	//申请一个变量内存
	int* pM = NULL;
	pM = (int*)malloc(sizeof(int));
	assert(pM);
	*pM = 1003;
	free(pM);
	//二维数组的申请
	//二级指针
	//二级指针申请
	int** pArray = NULL;
	pArray = (int**)malloc(sizeof(int*) * 4);  //p[0] p[1]  p[2]  p[3] 
	assert(pArray);
	for (int i = 0; i < 4; i++) 
	{
		pArray[i] = (int*)malloc(sizeof(int) * 3);
		assert(pArray[i]);
	}
	for (int i = 0; i < 4; i++) 
	{
		for (int j = 0; j < 3; j++) 
		{
			pArray[i][j] = i * j;
			printf("%d\t", pArray[i][j]);
		}
		printf("\n");
	}
	//释放顺序和申请顺序相反的
	for (int i = 0; i < 3; i++) 
	{
		free(pArray[i]);
	}
	free(pArray);
	//数组指针申请维数组
	int(*p2D)[4] = NULL;
	//(指针类型)malloc(sizeof(指针所指向的类型)*个数);
	p2D = (int(*)[4])malloc(sizeof(int[4]) * 3);
	assert(p2D);
	for (int i = 0; i < 3; i++) 
	{
		for (int j = 0; j < 4; j++) 
		{
			p2D[i][j] = i * j;
			printf("%d\t", p2D[i][j]);
		}
		printf("\n");
	}
	free(p2D);
	p2D = NULL;
	return 0;
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兴趣使然的Qsiri

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值