指针-指针运算

本文详细介绍了C语言中指针的基本概念,包括指针与地址的区别、空指针的使用、多级指针的定义及应用场景,以及指针在数组操作中的应用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>

//1、指针和地址有什么区别?
//指针:指针有类型   地址:没有类型,需要强制类型转换才能够赋值给指针变量
//int* p = (int *)0x44fc28;

//2、空指针
//注意:指针使用之前必须要有初始值(初始化)
/*
void main(){
	int* p;
	printf("%#x",p);
}
*/

//补充:
/*
void main(){
	//有的时候我们一时半会没有用到,但是有一个初始值,给一个NULL
	int* p = NULL;
	//NULL地址
	printf("地址:%#x",p);
	//取值:0x0000000  因为这个是操作系统所使用,一般应用程序不能够访问
	//printf("值:%d", *p);

	//判断空
	if (p == NULL){
		printf("为空.......");
	}

	//把10当做一个内存地址赋值给了指针变量(16进制)
	p = 200;
	//打印指针变量对应的值
	printf("%d\n", *p);
	//总结:由于数字比较小,系统本身已经占用这块内存区域,系统本身内存数据不允许访问
	//所以一般情况下,我们不会直接给指针变量赋值为整数

	getchar(); 
}
*/

//3、多级指针(二级指针)
//指针变量也是变量,同样占据了内存空间,同样有地址,
//因此可以用一个指针指向它,这就称之为二级指针
//补充:正常情况下最多就是三级指针
//多级指针的作用:删除链表、动态分配内存给二维数组等等......
/*
void main(){
	int a = 100;
	int b = 200;
	//a变量的地址
	int* p1 = &a;
	//打印指针的地址
	printf("p1地址:%#x\n", &p1);

	//二级指针
	int** p2 = &p1;

	//p2保存的数据是p1地址,*p2上的数据是p1上面数据,
	//p1保存的数据是a的地址,**p2实际上就是a的值
	**p2 = 1000;

	printf("二级指针地址:%#x\n",&p2);
	printf("a的值:%d", a);
	

	getchar();

}
*/

//4、指针的运算(赋值运算、算术运算)
/*
void main(){
	//赋值运算
	//int a = 200;
	//int* p = &a;

	//算数运算(+  -  *  /)
	//数组
	//总结一:ids常量指针,存储的是数组的首地址
	//总结二:数组在内存中排列是连续不断(线性排列)
	int ids[] = {23,15,67,38,99,70};
	//打印数组
	//printf("数组:%#x\n", ids);
	//数组第一个元素地址
	//printf("数组第一个元素地址:%#x\n",&ids[0]);

	//总结:p++每次向前移动sizeof(数据类型)个字节
	int* p = ids;
	//p++;
	//printf("地址:%#x  值:%d", p, *p);

	//遍历数组
	//传统方式
	//int i = 0;
	//for (; i < 6; i++){
		//printf("值:%d\n", ids[i]);
	//}
	//通过指针遍历
	for (; p < ids + 6; p++){
		printf("地址:%#x   值:%d\n",p, *p);
	}

	//注意:让指针递增或者递减,一般情况下只有在数组遍历的时候才有意义,
	//基于数组在内存中是线性排列的方式(连续不断)
	//注意:有可能会导致访问到其他的内存区域(例如:系统程序、第三方程序)

	getchar();
}
*/


//5、指针运算(通过使用指针循环给数组赋值)
/*
void main(){
	int ids[6];
	int* p = ids;
	//传统写法(高级写法)
	//赋值
	//int i = 0;
	//for (; i < 6; i++)
	//{
		//ids[i] = i;
	//}
	//输出
	//int j = 0;
	//for (; j < 6; j++){
		//printf("值:%d\n", ids[j]);
	//}

	//指针方式赋值
	int i = 0;
	for (; p < ids + 6; p++){
		*p = i;
		i++;
	}

	int j = 0;
	for (; j < 6; j++){
		printf("值:%d\n", ids[j]);
	}

	getchar();
}
*/

//6、数组内部指针的加减
/*
void main(){
	int ids[] = { 23, 15, 67, 38, 99, 70 };
	int* p = ids;

	p = p + 3;
	printf("值:%d  地址:%#x\n", *p, p);
	p = p - 2;
	printf("值:%d  地址:%#x\n", *p, p);
	getchar();
}
*/

//7、指针运算-指针大小比较
//指针大小比较:都是在遍历数组的时候运用,其他情况下没什么用
//指针相等比较:指针地址相等,并不代表值相等,因为指针有类型
/*
void main(){
	int* p1 = (int*)0x006578;
	double* p2 = (double*)0x006578;
}
*/

//8、指针运算-指针和数组的几种写法
/*
void main(){
	int ids[] = { 23, 15, 67, 38, 99, 70 };
	int i = 0;
	for (; i < 6; i++){
		//输出-高级写法(常规写法)
		//printf("%d  %#x\n", ids[i], &ids[i]);

		//之前分析了ids就是常量指针,就是一个首地址
		//以下分析是取地址
		//分析:ids是首地址
		//ids+0 等价于 &ids[0]
		//ids+1 等价于 &ids[1]
		//以此类推......
		//总结:ids+i 等价于 &ids[i]
		//分析取值
		//*(ids+0) 等价于 ids[0]
		//*(ids+1) 等价于 ids[1]
		//以此类推......
		//总结:*(ids+i) 等价于 ids[i]
		printf("%d  %#x\n",*(ids+i),ids+i);
	}

	
	printf("\n\n");

	int* p = ids;
	i = 0;
	for (; i < 6; i++){
		printf("%d  %#x\n", p[i], &p[i]);
		//printf("%d  %#x\n", *(p + i), p + i);
	}

	
	getchar();
}
*/

//9、指针与二维数组
void main(){
	//两行三列-二维数组
	int ids[2][3] = { 23, 15, 67, 38, 99, 70 };
	//遍历二维数组:外层循环控制行,内层循环控制列
	int i = 0;
	for (; i < 2; i++){
		int j = 0;
		for (; j < 3; j++){
			printf("值:%d 地址:%#x       ", ids[i][j],&ids[i][j]);
		}
		printf("\n");
	}

	printf("\n");
	printf("\n");

	//地址相同,并不代表值相同
	//总结
	//ids代表的是一个行指针,指向一个有三个元素的数组,大小12
	//&ids代表的是一个二维数组指针,当前二维数组6个元素,长度24
	//*ids代表的是一个指向该二维数组的数据类型的指针(相当于首地址:&ids[0][0])
	printf("ids:%#x  &ids:%#x  *ids:%#x\n",ids,&ids,*ids);
	printf("长度:%d  长度:%d  长度:%d\n", sizeof(*ids), sizeof(*&ids), sizeof(**ids));
	printf("值:%d\n", **ids);

	//推导过程分析
	//打印第二行,第二列
	printf("%d\n",ids[1][2]);

	//推导
	//ids + 0 代表第一行  第一行的第一个值
	//ids + 1 第二行(下一行)  第二行的第一个值
	//以此类推:ids + i
	//取每一行第一个元素的指针:*(ids+i)
	//第一行第一个元素指针:*(ids+0)
	//第二行第一个元素指针:*(ids+1)
	//以此类推:*(ids+i)

	//继续推理
	//取第一行第一个指针:*ids + 0
	//取第一行第二个指针:*ids + 1
	//取第一行第三个指针:*ids + 2
	//以此类推:*ids + j

	//继续推理
	//取第一行第二个指针:*(ids+0)+1
	//取第二行第二个指针:*(ids+1)+1
	//以此类推:*(ids+i)+j(这个公式获取的是地址,是一个指针变量)
	//*(*(ids+i)+j)

	printf("%d", *(*(ids+1)+2));

	getchar();
}


整理自课程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值