【C语言】指针详解(二)

目录

1.指针变量类型的意义

1.1指针的解引用

1.2指针 +  - 整数

1.3void*指针

2.const修饰指针

2.1const修饰变量

2.2const修饰指针变量


1.指针变量类型的意义

1.1指针的解引用

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

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

//代码1
#include<stdio.h>
int main()
{int a = 0x11223344;int* p = &a;*pa = 0;return 0;
}代码2
#include<stdio.h>
int main()
{int a = 0x11223344;char* p = (char*) & a;*pa = 0;return 0;
}

 

 

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

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

1.2指针 +  - 整数

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

代码运行结果如下

int main()
{int n = 10;char* pc = (char*)&n;int* pi = &n;printf("&n  =%p\n", &n);printf("pc  =%p\n", pc);printf("pc+1=%p\n", pc+1);printf("pi  =%p\n", pi);printf("pi+1=%p\n", pi+1);return 0;
}

 

⭐我们可以看出,char*类型的指针变量+1跳过1个字节,int*类型的指针变量+1跳过了4个字节。这就是指针变量的类型差异带来的变化。
🔺结论:指针的类型决定了指针向前或者向后走一步有多大(距离)。

1.3void*指针

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

举例:

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

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

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

 

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

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

2.const修饰指针

2.1const修饰变量

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

int main()
{int a = 10;a = 0;//a是可以修改的const int b = 20;b = 0;//b是不可修改的
}

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


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

如下代码:

int main()
{const int b = 20;int* pa = &b;*pa = 0;printf("%d", b);
}

 此时可以看到通过指针我们成功修改了b的值

我们可以看到这里b确实修改了,但是我们还是要思考一下,为什么b要被const修饰呢?就是为了不能被修改,如果p拿到b的地址就能修改b,这样就打破了const的限制,这是不合理的,所以应该让p拿到b的地址也不能修改b,那接下来怎么做呢?

2.2const修饰指针变量

void test1()
{int n = 10;int m = 20;int* p = &n;*p = 20;//ok?p = &m;//ok?//在这里无论是通过*p修改n的值,亦或是修改指针变量p的值都是可以的。
}
void test2()
{int n = 10;int m = 20;const int* p = &n;*p = 20;//ok?p = &m;//ok?//这里我们用const修饰*p,此时发现无法通过*p修改n的值,但是依然可以修改指针变量p的值。
}
void test3()
{int n = 10;int m = 20;int* const p = &n;*p = 20;//ok?p = &m;//ok?//这里我们用const修饰p,此时发现依然可以通过*p修改变量n的值。但是无法修改指针变量p的值。
}
void test4()
{int n = 10;int m = 20;const int* const p = &n;*p = 20;//ok?p = &m;//ok?//这里我们用const修饰p和*p,此时发现既不能通过*p修改变量n的值。也无法修改指针变量p的值。
}

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

 以上便是我为大家带来的指针详解(二)的内容,若有不足,望各位大佬在评论区指出,谢谢大家!可以留下你们点赞、收藏和关注,这是对我极大的鼓励,我也会更加努力创作更优质的作品。再次感谢大家!  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/293032.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题——LeetCode844

方法一 暴力法&#xff1a; 对两个字符串分别从头到尾遍历一遍&#xff0c;遇到#就删除#和它之前的那个字符&#xff0c;如果遇到#在字符串的第一位则只用删除#&#xff0c;最后将删除后的不含#的两个字符串进行比较是否一样 var backspaceCompare function(s, t) {for(var …

《Python Advanced Programming + Design Patterns + Clean Code》

清洁代码 — 学习如何编写可读、可理解且可维护的代码 高级Python编程知识 Python之常用设计模式 Advanced Programming装饰器 decorators生成器 & 迭代器with 上下文管理器面向对象Mixin 模式反射机制并发编程 Design Patterns设计模式分类简单工厂模式工厂模式 √抽象工厂…

用C#也能做机器学习?

前言✨ 说到机器学习&#xff0c;大家可能都不陌生&#xff0c;但是用C#来做机器学习&#xff0c;可能很多人还第一次听说。其实在C#中基于ML.NET也是可以做机器学习的&#xff0c;这种方式比较适合.NET程序员在项目中集成机器学习模型&#xff0c;不太适合专门学习机器学习&a…

GNSS技术在城市规划中的革新:精准定位引领智慧城市发展

随着城市化的快速推进&#xff0c;城市规划愈发关键&#xff0c;而全球导航卫星系统&#xff08;GNSS&#xff09;技术的广泛应用正为城市规划带来一场前所未有的变革。本文将深入探讨GNSS模块在城市规划中的多重应用&#xff0c;以及如何通过精准定位推动智慧城市的发展。 城市…

【Python小知识 - 6】:QLabel设置图片

文章目录 QLabel设置图片 QLabel设置图片 from PyQt5.QtWidgets import * from PyQt5.QtGui import * import sysapp QApplication(sys.argv)window QWidget()hbox QHBoxLayout(window)# 设置标签图片 lable QLabel() lable.setPixmap(QPixmap(./img/window.png).scaled(1…

【ARM Cortex-M 系列 5 -- RT-Thread renesas/ra4m2-eco 移植编译篇】

文章目录 RT-Thread 移植编译篇编译os.environ 使用示例os.putenv使用示例python from 后指定路径 编译问题_POSIX_C_SOURCE 介绍编译结果 RT-Thread 移植编译篇 本文以瑞萨的ra4m2-eco 为例介绍如何下载rt-thread 及编译的设置。 RT-Thread 代码下载&#xff1a; git clone …

听GPT 讲Rust源代码--src/tools(22)

File: rust/src/tools/tidy/src/lib.rs rust/src/tools/tidy/src/lib.rs是Rust编译器源代码中tidy工具的实现文件之一。tidy工具是Rust项目中的一项静态检查工具&#xff0c;用于确保代码质量和一致性。 tidy工具主要有以下几个作用&#xff1a; 格式化代码&#xff1a;tidy工具…

12.21_黑马数据结构与算法笔记Java

//最近在复习&#xff0c;&#xff0c;java的进度会比较慢一些 目录 219 排序算法 基数排序2 220 排序算法 java排序 221 排序 e01 根据另一个数组次序排序 222 排序 e02 根据出现频率排序 thinking&#xff1a;关于比较器 223 排序 e03 最大间距 解法1&#xff08;超出内…

【图神经网络 · 科研笔记5】异构信息网络,利用注意力选择元路径;利用进化邻域和社群实现自监督动态图嵌入,交叉监督对比学习;近期科研思维导图小汇总;

记录部分科研文献阅读相关内容【划重点】,主题“图神经网络”,仅学习使用。 🎯作者主页: 追光者♂🔥 🌸个人简介: 📝[1] CSDN 博客专家📝 🏆[2] 人工智能领域优质创作者🏆 🌟[3] 2023年城市之星领跑者TOP1(哈尔滨)🌿 🌿[4] 2022年度…

ACM32G1x3有那些优势?适用于那些产品上?

ACM32G1x3优势 • 320KB 程序Flash64KB SRAM&#xff0c;跑RTOS程序开发更加方便 • 从外挂Flash通过DMA搬运图片数据到PSRAM&#xff0c;无需打断程序运行 • 120MHz M33内核&#xff0c;处理性能佳 • 集成2路CAN接口&#xff0c;适合工控等需要CAN接口的场景 • QS…

SpringSecurity深度解析与实践(2)

目录 引言1.Springboot结合SpringSecurity用户认证流程1.1 配置pom文件1.2.配置application.yml 2.自定义MD5加密3.BCryptPasswordEncoder密码编码器4.RememberMe记住我的实现5.CSRF防御5.1.什么是CSRF 引言 上篇网址 1.Springboot结合SpringSecurity用户认证流程 1.1 配置p…