C语言指针进阶(1)(超详细)

前言:

 指针其实就是地址,而凡是存储在内存中的值都会有属于自己的地址,指针指向地址,这样我们就能通过指针间接操作变量。我们在指针初阶中介绍了指针的基本概念:如指针大小、野指针问题、指针间的关系运算等,在我们的指针进阶中,将会对指针进行进一步剖析,见识更深的指针!

正文:

  我们将在指针进阶中学习各种各样指针,比如字符指针、数组指针、函数指针等,这些指针种类虽多,但能力都很强大,作为进阶系列文章,涉及知识多多少少有点难度,但我们相信无论多么大的困难都无法阻挡我们的学习之路,因为每个人的潜力都是无限的,相信自己!

知不足而奋进,望远山而前行!!!

大家加油!!!

一、const修饰指针

首先,我们来讲一下const修饰指针的一些作用。

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

#include<stdio.h>int main()
{
int a=10;
a=20;
printf("%d\n",a);
}

这串代码带印出来就会是20,然后我们如果在int 的前面加上一个const,那a的值便无法被改变

因为const使a具有了常属性,常属性的意思就是不能被修改了。

下面我们来看一下const在指针中的应用。

如果我们非要去该下面a的值,那么可以这样做:

int main()
{
const int a=10;
int*p=&a;
*p=0;
printf("%d",a);}

如果我们这样写,a的值就可以被修改了。

int main(){
int a=10;
int const*p=&a;
int * const p=&a; return 0;
}

再看这串代码,我们可以发现const可以放在*的前面和后面,我们来看一下这两种写法的区别:

当我们这样写的时候,我们可以发现,a的值可以被改变,但是p无法重新赋值,无法将b的地址赋给p。

我们来这样看一下:

 我们可以看出,p作为一个指针,其可以存放一个地址,然后p可以指向a,然后p本身还有一个地址。

理解这一点之后,我们再看刚才那串代码,const限制的是p本身,p已经指向a地址,这时我我们想再让p指向b的地址是无法实行的,因为const会限制这一操作。但是我们可以改变a的值。

!!!!重点:const在修饰指针变量时,放在*的右边,限制的是指针变量本身,即p本身,指针变量不能在指向其他变量,但可以修改指针变量指向的内容。

再看另外一串代码:

int main()
{int a=10;
int b=20;
int const *p=&a;
p=&b
return 0;
}

运行这串代码之后我们发现是没有错误的,那就说明此时指针变量本身是可以改变的,但是指向的内容不可以修改。

!!!!重点:const在修饰指针变量时,放在*的左边,限制的是指针变量指向的内容,指针变量可以再次指向其他变量,但不可以修改指针变量指向的内容。

二、指针运算

指针的基本运算有三种,分别是:

  • 指针+-整数
  • 指针-指针
  • 指针的关系运算

我们再来想一下,指针的作用是什么,通俗的来讲就是访问内存的。

2.1指针+-整数

先来看一下指针+1

int a=10;

int*p=&a;

p+1 -->表面上是加1,但其实是跳过4个字节,

其实就是跳过1*sizeof(type)个字节。

不同的type跳过的字节不同。

如果是char类型,那便是跳过一个字节

接下来我们来考虑一下他有什么作用呢:

 我们都知道,数组在内存中的存储是连续的,只要知道1第一个元素的地址,顺藤摸瓜就能找到后面的所有元素。

int main()
{int arr[10]={1,2,3,4,5,6,7,8,9,10};
int sz=sizeof(arr).sizeof(arr[0]);
int*p=&arr[0];
for(int i=0;i<sz;i++)
{printf("%d ",*p);p+=1;}
return 0;
}

 这样我们便可以通过指针的方式来打印这个数组,这便是指针的一个作用。

就像我们上面说的,每次p+1跳过4个字节,来到下一个数组元素,然后打印。

2.2指针-指针

我们再来看一下指针-指针的应用:

int main()
{int arr[10]={1,2,3,4,5,6,7,8,9,10};
printf("%zd\n",&arr[9]-&arr[0]);return 0;}

这样我们便可以得到一个9,这便是指针-指针的应用,

 
int my_strlen(char*str)
{
int count=0;
while(*str!='\0')
{
count++;
str++;
}
}int main()
{
char arr[]="abcdef";
//[a b c d e d \0]
int len=my_strlen(arr);
printf("%d\n",len);
return 0;
}

这也是指针-指针的一种应用,大家可以看一下。 

2.3指针的关系运算

 指针的关系运算其实就是指针和指针比较大小,即地址和地址比较大小。

int main()
{int arr[]={1,2,3,4,5,6,7,8,9,10};int sz = sizeof(arr)/sizeof(arr[0]);
int*p=arr;//arr[0]while(p<sz+arr)
{printf("%d ",p);
p++;
}
}

这里的iwhile语句中,便是指针之间的关系运算。

三、assert断言

对于断言,相信大家都不陌生,大多数编程语言也都有断言这一特性。简单地讲,断言就是对某种假设条件进行检查。在 C 语言中,断言被定义为宏的形式(assert(expression)),而不是函数,其原型定义在<assert.h>文件中。其中,assert 将通过检查表达式 expression 的值来决定是否需要终止执行程序。也就是说,如果表达式 expression 的值为假(即为 0),那么它将首先向标准错误流 stderr 打印一条出错信息,然后再通过调用 abort 函数终止程序运行;否则,assert 无任何作用。

默认情况下,assert 宏只有在 Debug 版本(内部调试版本)中才能够起作用,而在 Release 版本(发行版本)中将被忽略。当然,也可以通过定义宏或设置编译器参数等形式来在任何时候启用或者禁用断言检查(不建议这么做)。同样,在程序投入运行后,最终用户在遇到问题时也可以重新起用断言。这样可以快速发现并定位软件问题,同时对系统错误进行自动报警。对于在系统中隐藏很深,用其他手段极难发现的问题也可以通过断言进行定位,从而缩短软件问题定位时间,提高系统的可测性。

assert(p!=NULL);

 例如这行代码,便可以验证p是否等于NULL,如果不等于NULL,程序继续进行,如果为假,返回值则为0,assert()就会报错

assert()的使用对程序员十分友好,使用它有以下几个好处,

它不仅能自动标识文件和出现的问题的行号,还有一种无需更改代码就能开启或关闭assert()的机制,如果已经确认程序没问题,不需要再做断言,就在#include<assert.h>语句前面,定义一个宏NDEBUG就可以了

看一下下面两张图片:

 这样我们便很容易的可以搞清楚assert()断言的作用。

assert    出现报错的时候,直接就会报错,指明什么文件,哪一行

并且关闭assert之后,在Release版本中,不会影响运行效率。

#include<stdio.h>int my_strlen(char* str)
{int count = 0;assert(str != NULL);while (*str != '\0') {count++;str++;}
}int main()
{char arr[] = "abcdef";int len = my_strlen(arr);printf("%d", len);return 0;
}

这样写可以防止传参是=时传的是空指针。

四、指针的使用和传址调用

写一个函数,交换两个函数的内容

#include<stdio.h>void swap(int x, int y) {int tmp = x;x = y;y = tmp;
}int main()
{int a = 10;int b = 20;printf("交换前:a=%d b=%d", a, b);swap(a, b);printf("交换后:a=%d b=%d\n", a,b);return 0;
}

首先我们看一下上面的代码,看似是可以的,我们运行一下:

我们发现a与b的值并未改变,这是为什么呢, 那是因为我们在调用swap函数时,值虽然能传过去,但是只有x与y的值发生互换,无法改变a与b的值,x与a的地址不同,y与b的值也不同,所以他们不会改变a与b的值,那该怎样去写呢?

上面我们其实就是在传值调用,即传过去a与b的值,下面我们将通过传址调用来改变a与b的值。

#include<stdio.h>void swap(int *pa, int *pb) {int tmp = *pa;*pa = *pb;*pb = tmp;
}int main()
{int a = 10;int b = 20;printf("交换前:a=%d b=%d\n", a, b);swap(&a, &b);printf("交换后:a=%d b=%d\n", a,b);return 0;
}

这样便可以实现a与b值的交换。

总结:

本次我们对指针进阶的一部分内容进行了阐述,如const修饰指针,assert断言部分都是比较重要的,希望对大家有所帮助,对哪里有疑惑的话可以在评论区留下你的疑惑。

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

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

相关文章

CTF CRYPTO 密码学-7

题目名称&#xff1a;敲击 题目描述&#xff1a; 让我们回到最开始的地方 0110011001101100011000010110011101111011011000110110010100110011011001010011010100110000001100100110001100101101001101000011100001100011001110010010110100110100011001000011010100110000…

贪吃蛇游戏的实现

一.技术要点: 贪吃蛇需要掌握: c语言函数,枚举,结构体,动态内存管理,预处理指令,链表,Win32 API等 二.Win32 API 1.Win32 API简介 windows可以帮应用程序卡其视窗,描绘图案,使用周边设备,,Win32 API就是windows32位平台上的应用程序编程接口 2.控制台程序 (1).使用cmd命令…

【爬坑】临时修复To connect to xxx insecurely, use `--no-check-certificate‘报错

解决方案&#xff1a;wget请求时跳过证书验证。 sudo vim /etc/wgetrc 插入一行&#xff1a; check_certificate off 重新运行wget命令即可。

Markdown(2篇文章学会Markdown第二篇

目录 1. 图片1.1 行内形式图片&#xff1a;\!\[Alt text]\(/path/to/img.jpg "Optional title")1.2 参考形式图片&#xff1a;\!\[内容]\[1] \[1]: image_url "alt 提示" 2. 列表2.1 无序列表&#xff1a;*、或-2.2 有序列表&#xff1a;数字接着一个英文…

Redis学习——高级篇④

Redis学习——高级篇④ Redis7高级之Redis与Mysql数据双写一致性工程案例&#xff08;四&#xff09; 4.1 MySQL主从复制原理4.2 canal 工作原理4.3 mySQL->canal->redis 双写一致性1.环境2.配置Mysql3.配置canal4. Canal客户端&#xff08;Java编写&#xff0…

双非本科准备秋招(10.2)—— JVM3:垃圾收集器

垃圾收集器 分为七种&#xff0c;如下&#xff1a; 从功能的角度分为 1、串行&#xff1a;Serial、Serial Old 2、吞吐量优先&#xff1a;Parallel Scavenge、Parallel Old 3、响应时间优先&#xff1a;CMS 吞吐量优先VS响应时间优先 吞吐量运行用户代码时间/(运行用户代码…

AI-数学-高中-11-指数函数

原作者视频&#xff1a;初等函数】3指数函数&#xff08;基础&#xff09;_哔哩哔哩_bilibili 指数函数、幂函数&#xff1a; 注意&#xff1a;分段函数注意看分界点。 注意&#xff1a;复合函数&#xff0c;采用换元法分解为外层和内层2个函数&#xff0c;先计算外层函数t和画…

神经网络建立(结果可变)最小神经元

目录 介绍&#xff1a; 初始化&#xff1a; 建模: 预测&#xff1a; 改变结果&#xff1a; 介绍&#xff1a; 在深度学习中&#xff0c;神经元通常指的是人工神经元&#xff08;或感知器&#xff09;&#xff0c;它是深度神经网络中的基本单元。深度学习的神经元模拟了生…

如何成为一个更好的沟通者?

新年伊始&#xff0c;我想跟大家分享9条我给自己定下的「沟通准则」。 这9条准则&#xff0c;是我对自己的要求&#xff0c;也是我身体力行践行了许多年的做法。我可能也没能践行得非常完美&#xff0c;但这也是我一直在努力的目标。 如果你希望能够跟别人「好好说话」&#xf…

《SPSS统计学基础与实证研究应用精解》视频讲解:在线分析处理报告

《SPSS统计学基础与实证研究应用精解》5.1 视频讲解 视频为《SPSS统计学基础与实证研究应用精解》张甜 杨维忠著 清华大学出版社 一书的随书赠送视频讲解5.1节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。本书旨在手把手教会使…

《信息系统项目管理师》备考计划

《信息系统项目管理师》证书价值和作用 信息系统项目管理师证书的价值体现在提升专业知识、助力职业发展、职称评定、技能补贴和人才引进或积分落户等方面。 一方面可以通过系统学习&#xff0c;可以显著提高自己在信息系统项目管理领域的专业水平。方便自己以后向更多的方向…

sqli-labs部署及sqli-labs靶场第一关

部署 一、环境安装 1.下载phpstudy&#xff0c;下载链接&#xff1a;小皮面板(phpstudy) - 让天下没有难配的服务器环境&#xff01; &#xff0c;傻瓜式的安装过后打开软件进入如下界面&#xff0c;我们开启nginx和mysql &#xff01;&#xff01;&#xff01;&#xff0…