当前位置: 首页 > article >正文

深入理解指针(二)

深入理解指针变量(一)知识回顾:深入理解指针(一)-CSDN博客

3. 指针变量类型的意义

指针变量的大小与类型无关,只要是指针变量,在同一个平台下,大小都是一样的,为什么还要有各种各样的指针类型呢?

3.1 指针的解引用

对比以下两段代码,主要在调试时观察内存的变化。

代码1:

int main()
{
	int n = 0x11223344;
	int* pi = &n;
	*pi = 0;
	return 0;
}

代码2:


int main()
{
	int n = 0x11223344;
	char* pi = (char*) & n;
	*pi = 0;
	return 0;
}

通过调试我们可以看到,代码1会将n的4个字节全部改为0,但是代码2只是将n的第一个字节改为0。

结论:指针的类型决定了,对指针解引用的时候有多大的权限(一次能操作几个字节)。比如:char*的指针解引用就只能访问一个字节,而int*的指针解引用就能访问四个字节。

3.2 指针+-整数

先看一段代码,调试观察地址的变化。

int main()
{
	int n = 10;
	char* pc = (char*)&n;
	int* pi = &n;

	printf("%p\n", &n);
	printf("%p\n", pc);
	printf("%p\n", pc+1);
	printf("%p\n", pi);
	printf("%p\n", pi+1);
	return 0;
}

代码运行结果如下:

 我们可以看出,char*类型的指针变量+1跳过1个字节,int*类型的指针变量+1跳过了4个字节.这就是指针变量的类型差异带来的变化。指针+1,其实是跳过1个指针指向的元素。指针可以+1,那也可以-1.

结论:指针的类型决定了指针向前或者向后走一步有多大(距离)。

3.3 void*指针

在指针类型中有一种特殊的类型是void*类型的,可以理解为无具体类型的指针(或者叫泛型指针),这种类型的指针可以用来接收任意类型的地址。但是也有局限性,void*类型的指针不能直接进行指针的+-整数和指针的解引用操作。

举例:

int main()
{
	int a = 10;
	int* pa = &a;
	char* pc = &a;
	return 0;
}

在上面的代码中,将一个int类型的变量的地址赋值给一个char*类型的指针变量。编译器给出一个警告,是因为类型不兼容。而使用void*类型就不会有这种问题。

使用void*类型的指针接收地址:

int main()
{
	int a = 10;
	void* pa = &a;
	void* pc = &a;

	*pa = 10;
	*pc = 0;
	return 0;
}

 VS编译代码的结果:

这里我们可以看到,void*类型的指针可以接收不同类型的地址,但是无法直接进行指针运算。

那么void*类型的指针是使用在函数参数的部分,用来接收不同数据类型的地址,这样的设计可以实现泛型编程的效果。使得一个函数来处理多种类型的数据。

4. const修饰指针

4.1 const修饰变量

变量是可以被修改的,如果把变量的地址交给一个指针变量,通过指针变量的也可以修改这个变量。但是如果我们希望一个变量加上一些限制,不能被修改,怎么做呢?这就是const的作用。

int main()
{
	int m = 0;
	m = 20;
	const int n = 0;
	n = 20;
	return 0;
}

 上述代码中n是不能被修改的,其实n本质是变量,只不过被const修饰后,在语法上加了限制,只要我们在代码中对n进行修改,就不符合语法规则,就报错,致使没法直接修改n。

但是如果我们绕过n,使用n的地址,去修改n就能做到了,虽然这样做是在打破语法规则。

int main()
{
	const int n = 0;
	printf("n=%d\n", n);
	int* p = &n;
	*p = 20;
	printf("n=%d\n", n);
	return 0;
}

输出结果:

我们可以观察到这里n确实被修改了,但是我们要考虑一下,为什么n要被const修饰呢?就是为了不能被修改,如果p拿到n的地址就可以进行修改,这样就打破了语法规则,这是不合理的,所以应该让p拿到n的地址也不能进行修改。

4.2 const修饰指针变量

一般来讲const修饰指针变量,可以放在*的左边,也可以放在*的右边,意义是不一样的。

int * p//没有const修饰
int count * p//const放在*的左边做修饰
int * const p//const放在*的右边做修饰

我们看下面的代码,来具体分析一下:

void test1()
{
	int n = 10;
	int m = 20;
	int* p = &n;
	*p = 20;
	p = &m;
}

void test2()
{
	int n = 10;
	int m = 20;
	const int* p = &n;
	*p = 20;
	p = &m;
}

void test3()
{
	int n = 10;
	int m = 20;
	int* const p = &n;
	*p = 20;
	p = &m;
}

void test4()
{
	int n = 10;
	int m = 20;
	int const* const p = &n;
	*p = 20;
	p = &m;
}


int main()
{
	test1();
	test2();
	test3();
	test4();
	return 0;
}

结论:const修饰变量的时候

  • const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。但是指针变量本身的内容可变。
  • const如果放在*右边,修饰的是在指针变量本身,保证了指针变量内容不能修改,但是指针指向的内容,可以通过指针修改。

完。


http://www.kler.cn/a/304367.html

相关文章:

  • python+reportlab创建PDF文件
  • QT从入门到精通(三)——实现文件列表遍历的图像浏览器
  • CSS中的calc函数使用
  • 数据结构(Java版)第六期:LinkedList与链表(一)
  • 重温设计模式-外观模式和适配器模式的异同
  • 从 GitLab.com 到 JihuLab.com 的迁移指南
  • vue3里根据配置信息显示el-button的问题
  • iOS中的链表 - 单向链表
  • 多核DSP(6000系列)设计与调试技巧培训
  • 【案例70】invalid secrity token(null)
  • 【SpringBoot】调度和执行定时任务--DelayQueue (附demo)
  • STM32——看门狗通俗解析
  • 【Linux网络】详解TCP协议(1)
  • C++特性--动态内存和智能指针
  • 工作睡觉监测识别摄像机
  • fly专享
  • 【三】TDengine 3.3.2 生产级别集群搭建
  • 【互联网的低潮期】
  • 相亲交友中的用户画像构建方法探讨
  • 【拥抱AI】使用Conda的一些常见命令
  • 如何判断硬盘是不是固态硬盘?介绍几种简单有效方法
  • Java多线程——模拟看病叫号
  • 聚鼎科技:现在做装饰画是靠谱的吗
  • pandas读取xlsx文件使用sqlachemy写到数据库
  • YOLOv5改进 | 模块缝合 | C3 融合RFAConv和CBAM注意力机制 【二次融合 小白必备】
  • 通过 汇编 分析 结构体