5.C语言之指针

本文详细解析了指针在C语言中的来源、使用方法、注意事项以及与数组、多维数组的交互,包括取址运算符、间接寻址运算符、const保护参数、指针作为返回值、与数组的关系、指针与多维数组的应用等关键概念。

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

1. 指针的来源

在当代,大多数的现代计算机都会把内存分割成字节,每个字节都有着其唯一的地址。可执行程序由代码和数据两部分构成,而程序中的每个变量都占有着一个或多个字节,也就是说,每个变量都有着自己的地址。而这个就是指针的来源。

其实每个地址就是一个数,但是我们却不能用数来表示地址,存储地址,我们需要用指针变量。例如int *p = i,我们就可以说p是指针变量,存储着变量i的地址。

那么我们说int *p中,p就是指向int 类型对象的指针变量。

2. 取址运算符和间接寻址运算符

&,取址运算符,如果x是变量,那么&x就是变量x所在的地址。

*,间接寻址运算符,如果p是指针变量,*p就代表p所指向的变量的值。

当我们在程序中声明int *p时,其实并没有让p指向任何地址,只是一个空指针,我们也称之为悬浮指针,在程序中,我们应该尽量避免这样的状况,应该尽量当声明的同时进行初始化。否则当今后不小心对*p进行赋值时,如果p恰好指向了某一块系统内存地址,就会造成系统的崩溃。

其实我们第一次接触取址运算符,应该是应用于scanf,现在我们来想想scanf(“%d”,&a)的含义,其实就是告诉scanf函数,要把读取的值放到哪个地址的下面。

3. const保护参数

我们之前说过const代表常量,不允许改变,那么我们也可以将const应用于指针参数上。例如:

void Test(const int *p)就代表*p是不可以改变的,意思也就是p所指向的整数不能被改变。

void Test(int * const p)则代表,p是不可以被改变的,也就是说p只能指向这一块地址。

void Test(const int * const p)则代表,p只可以指向这一块地址,并且这一块地址的数据不能被改变。

4.指针作为返回值

这里我只提一点,不要反悔局部变量的指针变量,因为局部变量出了作用域马上被回收,这时,该指针也就指向了一块废弃的地址。

当然,我们可以返回某些参数的地址,外部变量和静态变量的地址。总之,要确保该指针指向的是一块未经回收的地址即可。

 

 

 

5. 指针和数组

这个在最初学习C语言时就学过了,在此只是简单提下。看一段代码:

 

  1. #define SIZE 10  
  2. int main (void)  
  3. {  
  4.     int a[SIZE],*p,sum;  
  5.     int i;  
  6.     p=a;  
  7.     sum=0;  
  8.     for(i =0;i<SIZE;i++)  
  9.     {  
  10.         a[i]=i+1;  
  11.     }  
  12.     for(;p<&a[SIZE];p++)  
  13.     {  
  14.         sum+=*p;  
  15.     }  
  16.     printf("%d",sum);  

 

很简单的一段代码,就是通过指针来访问数组元素,在此只提一点,就是&a[SIZE],虽然a[SIZE]不存在,数组的最后一个元素时a[SIZE-1],但是C编译器不会对下标进行越界检查,也就是说a[SIZE]一样可以访问,所以我们可以用这样的方式来终止for循环。

另外,面对指针访问数组还是下标访问数组,都是围绕着访问效率来的。其实这依赖于不同编译器的具体实现,在C标准中并无提及。

6. 指针与多维数组

这个在我大学学C语言时,一直都没有理解,不过现在看来比较容易了。

二维数组实际上在存储上也是一段连续的内存空间,因此我们可以将二维数组当做一维数组来对待,如下面的代码:

 

  1. #define ROW 3  
  2. #define COL 5  
  3. int main (void)  
  4. {  
  5.     int a[ROW][COL],*p,sum;  
  6.     int i,j;  
  7.     p=&a[0][0];  
  8.     sum=0;  
  9.     for(i =0;i<ROW;i++)  
  10.     {  
  11.         for(j=0;j<COL;j++)  
  12.         {  
  13.             a[i][j]=j+1;  
  14.         }  
  15.     }  
  16.     while(p<=&a[ROW-1][COL-1])  
  17.     {  
  18.         sum+=*(p++);  
  19.     }  
  20.     printf("%d",sum);  

 

但是这样做看起来可读性并不好,对于一些老编译器来说这样做的效率较高,可是对于现代编译器来说已经没有了这样的优势。

因此我们一般应该这样来做,我们知道,对于二维数组来说,例如a[i][j] ,其实a[0]代表的就是第一行的首元素的地址。那么我们就可以利用这个来访问多维数组元素:

 

  1. #define ROW 3  
  2. #define COL 5  
  3. int main (void)  
  4. {  
  5.     int a[ROW][COL],*p,sum;  
  6.     int i,j;  
  7.     sum=0;  
  8.     for(i =0;i<ROW;i++)  
  9.     {  
  10.         for(j=0;j<COL;j++)  
  11.         {  
  12.             a[i][j]=j+1;  
  13.         }  
  14.     }  
  15.     for(i=0;i<ROW;i++)  
  16.     {  
  17.         for(p=a[i];p<a[i]+COL;p++)  
  18.         {  
  19.             sum+=*p;  
  20.         }  
  21.     }  
  22.     printf("%d",sum);  

 

 

Windows 系统修复工具主要用于解决 Windows 11/10 系统中的各种常见问题,具有操作简单、功能全面等特点: 文件资源管理器修复:可解决文件资源管理器卡死、崩溃、无响应等问题,能终止崩溃循环。还可修复右键菜单无响应或选项缺失问题,以及重建缩略图缓存,让图片、视频等文件的缩略图正常显示,此外,还能处理桌面缺少回收站图标、回收站损坏等问题。 互联网和连接修复:能够刷新 DNS 缓存,加速网页加载速度,减少访问延迟。可重置 TCP/IP 协议栈,增强网络连接稳定性,减少网络掉线情况,还能还原 Hosts 文件,清除恶意程序对网络设置的篡改,保障网络安全,解决电脑重装系统后网络无法连接、浏览器主页被篡改等问题。 系统修复:集成系统文件检查器(SFC),可自动扫描并修复受损的系统文件。能解决 Windows 激活状态异常的问题,还可重建 DLL 注册库,恢复应用程序兼容性,解决部分软件无法正常运行的问题,同时也能处理如 Windows 沙箱无法启动、Windows 将 JPG 或 JPEG 保存为 JFIF 等系统问题。 系统工具维护:提供启动管理器、服务管理器和进程管理器等工具,用户可控制和管理启动程序、系统服务和当前运行的进程,提高系统的启动和运行速度,防止不必要的程序和服务占用系统资源。还能查看系统规格,如处理器线程数、最大显示分辨率等。 故障排除:集成超过 20 个微软官方诊断工具,可对系统问题进行专业排查,还能生成硬件健康状态报告。能解决搜索和索引故障、邮件和日历应用程序崩溃、设置应用程序无法启动等问题,也可处理打印机、网络适配器、Windows 更新等相关故障。 其他修复功能:可以重置组策略设置、catroot2 文件夹、记事本等多种系统设置和组件,如重置 Windows 应用商店缓存、Windows 防火墙设置等。还能添加重建图标缓存支持,恢复粘滞便笺删除
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值