news 2026/4/15 15:02:56

指针1(内存和地址的认识、指针变量的创建和使用、指针运算)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
指针1(内存和地址的认识、指针变量的创建和使用、指针运算)

文章目录

    • 一、内存和地址
    • 二、指针变量和地址
      • 2.1 取地址操作符 '&'
      • 2.2 创建指针变量
      • 2.3 使用指针变量
    • 三、指针变量类型的意义
      • 3.1 指针的解引用
      • 3.2 void* 指针
    • 四、指针运算
      • 4.1 指针 + - 整数
      • 4.2 指针 - 指针
      • 4.3 指针的关系运算
    • 五、const修饰指针
      • 5.1 const 修饰变量
      • 5.2 const修饰指针变量
    • 六、野指针
      • 6.1野指针的成因
        • 6.1.1 指针未初始化
        • 6.1.2 指针越界访问
        • 6.1.3 指针指向的空间释放
      • 6.2 如何避免野指针
        • 6.2.1 指针初始化
        • 6.2.2 小心指针越界
        • 6.2.3 避免返回局部变量的地址
    • 七、assert断言
    • 八、传值调用和传址调用
      • 8.1 传值调用
      • 8.2 传值调用

一、内存和地址

在计算机处理数据的时候,数据都需要先从内存当中读取出来,处理完后的数据还需放回内存当中;那么从内存中拿取数据处理完后又该如何放回到原来的空间呢?我们都知道,在我们购买电脑的时候有8G、16G、32G等更高的内存,那么这些内存空间如何高效的管理呢?
其实也就是把整个内存单元逻辑划分为多个小的内存单元,每个小的内存单元占1个字节,而每个小的内存单元都有一个独属于自己的地址,这些地址就像是一个个房间的门牌号,正是有了这些’‘门牌号’',计算机才能够准确且高效的对数据进行查找处理,处理完后再准确的放回

二、指针变量和地址

有了上面的概念后,我们就能更好的理解,在C语言中创建一个变量,其实就是向内存中申请一块空间,这片空间是这个变量独属的,比如:当创建一个int类型的变量a的时候,就会向内存申请一块四个字节的空间,用于存放int类型的变量a
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/67f6188848504469b45d37892886adf1.png
当我们想要取出a的地址的时候需要使用到一个操作符——取地址操作符 ’ & ’

2.1 取地址操作符 ‘&’

&a取出的地址是a所占的四个字节中地址较小的那一个字节的地址

2.2 创建指针变量

当我们想要将取出来的a的地址存放起来的时候,就需要创建一个指针变量,指针变量就是用来存放地址的变量,所占大小为4个字节(x86环境)或8个字节(x64环境)

int a = 5; int* p = &a;//创建一个指针变量p

int表示取地址的对象a为int类型,所以在我们创建一个指针变量时,要根据取地址的对象的类型来确定指针变量的类型,而’ * '表示该变量为指针变量

2.3 使用指针变量

当我们创建了a的指针变量后,我们要通过p对a的值进行操作的时候,就需要用到 ’ * ‘解引用操作符,解引用操作符’ * ‘不同于创建指针变量时所使用的’ * ',一个是对指针变量p的说明,一个是对指针变量p的解引用
例如:

#include<stdio.h>intmain(){inta=5;int*p=&a;*p=10;//通过指针变量p,将a的值修改为10printf("%d",a);return0;}

为什么通过指针变量p能够更改a的值呢?其实是因为p存放的就是a的地址,对p解引用后进行操作就是对a进行操作

三、指针变量类型的意义

3.1 指针的解引用

指针变量的大小和类型无关,在同一平台下,同一环境中,指针变量的大小都是相同的,既然大小都相同,为什么还要有各种各样的指针类型呢?
其实指针类型是有特殊的含义的,当指针类型不同时,所能操作的字节数也可能不同
例如:

//代码1:#include<stdio.h>intmain(){inta=0x11223344;int*p1=&a;*p1=0;printf("%d",a);}//代码2:#include<stdio.h>intmain(){inta=0x11223344;char*p1=&a;*p1=0;printf("%d",a);}

当我们运行这两个代码的时候就会发现:

代码1会将a的4个字节全部改成0,而代码2只会将a的第一个地址改为0
由此,我们可以得到一个结论:指针的类型决定了对指针解引用时有多大的权限(一次能够操作多少个字节)
就比如上方的代码:int* 的指针解引用就能访问一个字节,而char*的指针解引用只能访问1个字节

3.2 void* 指针

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

#include<stdio.h>intmain(){inta=0x11223344;void*p=&a;*p=10;printf("%d",a);}

当我们运行这段代码时,编译器就会报错

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

四、指针运算

4.1 指针 + - 整数

因为数组在内存种是连续存储的,所以,当我们知道首元素地址的时候,就可以根据首元素地址+整数,从而找到后面的元素
例如:

#include<stdio.h>intmain(){intarr[]={1,2,3,4,5,6,7,8,9};int*p=arr;//数组名==数组首元素地址intsz=sizeof(arr)/sizeof(arr[0]);inti=0;for(i=0;i<sz;i++){printf("%d ",*(p+i));//指针+整数}}

通过上面的代码就能打印出数组arr中所有的元素
需要注意的是,指针变量±指针跳过的字节数跟指针类型有关,比如一个int类型的指针变量+1就是跳过4个字节,一个char类型的指针变量+1就是跳过1个字节,所以在进行指针±运算时,一定要正确的判断该使用哪种类型的指针变量

4.2 指针 - 指针

当我们需要求一个字符串的长度的时候,就可以使用指针-指针运算

#include<stdio.h>size_tmy_strlen(char*ps1){char*ps2=ps1;while(*ps2!='\0'){ps2++;}returnps2-ps1;}intmain(){chars[]="abcdefg";size_tret=my_strlen(s);printf("%zu\n",ret);return0;}

4.3 指针的关系运算

#include<stdio.h>intmain(){chars[]="abcdefg";char*p1=s;char*p2=&s[1];if(p1>p2)//p1和p2两个地址相比较,看哪个地址更大{printf(">");}else{printf("<=");}return0;}

五、const修饰指针

5.1 const 修饰变量

const用于给变量加上限制,使得该变量无法被改变
例如:

#include<stdio.h>intmain(){constinta=10;a=20;}

当我们对被const修饰的变量进行修改时,编译器就会报错

5.2 const修饰指针变量

const修饰指针变量,可以放在’ * ‘的左边,也可以放在’ * ‘的右边
当const放在’ * '左边的时候,指针所指向的内容被限制了,不能通过指针对指针指向的内容进行修改,但是指针变量本身的值可以修改

指针变量本身的值可以修改:

#include<stdio.h>intmain(){inta=10;intb=20;constint*p=&a;p=&b;printf("%d\n",*p);}

当const放在’ * ‘右边的时候,修饰的是指针变量本身,保证了指针变量本身不能够被修改,但是指针指向的内容可以被修改

当然,const也可以同时存在与’ * '的左右两边,表示该指针变量本身和所指向的内容都不能被修改

六、野指针

野指针就是指向的位置是不可以预知的(随机的、不正确的、没有明确限制的)

6.1野指针的成因

6.1.1 指针未初始化
#include<stdio.h>intmain(){int*p;*p=20;printf("%p\n",*p);}

像这样不初始化指针变量而直接使用时,编译器就会报错

6.1.2 指针越界访问

假设一个数组有10个元素,我们创建一个指针变量p,把数组首元素地址放进p里面,然后*(p+10),这样就会出现指针越界访问的问题,因为整个数组一共就只有十个元素,我们对*(p+10)其实就是指向了第11个元素,这样就超出了数组arr的范围,这就使得p成为了野指针,并且p所指向的内容是未知的

6.1.3 指针指向的空间释放
#include<stdio.h>int*test(){intn=100;return&n;}intmain(){int*p=test();printf("%d",*p);}

当出test函数时,局部变量所申请的空间会返还给内存

6.2 如何避免野指针

6.2.1 指针初始化

当我们明确知道创建的指针需要指向哪里的时候,我们就可以直接对该指针变量进行赋值;而当我们需要创建一个指针,但还不知道这个指针需要指向哪里的时候,可以先赋值NULL。
NULL指针是C语言所定义的一个标识符常量,值是0,这个地址是无法使用的,读写该地址会报错

int* p = NULL;
6.2.2 小心指针越界

一个程序向内存申请了哪些空间,通过指针也只能访问那些空间,不能超出访问范围,超出了就是越界访问

6.2.3 避免返回局部变量的地址

当我们调用一个函数时,不要使用该函数所返回的指向该函数内部局部变量的地址

七、assert断言

assert.h头文件定义了宏assert(),用于在运行时确保程序符合指定的条件,如果不符合,就报错中职运行。这个宏常常被称为断言
例如:

八、传值调用和传址调用

设计一个函数,用于交换a和b的值

8.1 传值调用

运行这个代码后,发现,a和b的值并没有成功交换,为什呢?
其实是因为,a和b的值传递给了Swap函数,Swap函数内部创建了x和y两个变量用于接收a和b的值,但是,当我们分别打印x、y和a、b的地址的时候,就会发现,他们对应的地址并不相同,也就是说x、y其实是独立的空间,对该空间进行修改,并不会影响到a、b的值,所以当Swap函数调用完返回main函数后,a和b的值并没有交换

8.2 传值调用

因此,当我们想要交换两个值的时候,就需要用到传址调用,把两个参数对应的地址传递给Swap函数,Swap函数用两个指针变量来进行接收,这样,对x和y的修改也会影响到a和b

传址调用可以让函数与主函数之间建立真正的联系,在函数内部可以修改主调函数中的变量;所以,在以后写代码时,只是需要主调函数中的变量来实现计算的时候,就可以采用传值调用;如果函数内部要修改主调函数中变量的值,就需要使用传址调用


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 7:46:54

Zotero插件市场:让插件管理效率飞升的黑科技

Zotero插件市场&#xff1a;让插件管理效率飞升的黑科技 【免费下载链接】zotero-addons Zotero add-on to list and install add-ons in Zotero 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-addons 01 当你还在手动下载插件时&#xff0c;高手已经实现一键管理…

作者头像 李华
网站建设 2026/4/13 18:36:20

Qwen3-VL-4B Pro部署案例:中小企业AI客服图文识别落地实践

Qwen3-VL-4B Pro部署案例&#xff1a;中小企业AI客服图文识别落地实践 1. 为什么中小企业需要看得懂图的AI客服&#xff1f; 你有没有遇到过这样的客户咨询&#xff1f; “我拍了张商品故障图&#xff0c;能帮我看看哪里坏了&#xff1f;” “这张发票截图里金额对不对&#…

作者头像 李华
网站建设 2026/4/9 15:45:06

从0开始学大模型调用:Qwen3-1.7B让AI对话更简单

从0开始学大模型调用&#xff1a;Qwen3-1.7B让AI对话更简单 你是不是也遇到过这些情况&#xff1a; 想试试最新大模型&#xff0c;却被复杂的环境配置卡住&#xff1b; 看到一段调用代码&#xff0c;却不知道怎么改才能跑通&#xff1b; 明明只是想问一句“今天天气怎么样”&a…

作者头像 李华
网站建设 2026/3/31 1:15:44

企业级隐私保护!GLM-4-9B本地化部署实战指南

企业级隐私保护&#xff01;GLM-4-9B本地化部署实战指南 1. 为什么企业需要“真本地”的大模型&#xff1f; 你有没有遇到过这些场景&#xff1f; 法务部门想让AI快速梳理一份200页的并购协议&#xff0c;但不敢把文件上传到任何公有云&#xff1b; 研发团队希望用大模型分析…

作者头像 李华
网站建设 2026/4/7 16:36:26

如何重新访问Flash内容?CefFlashBrowser实现SWF播放与本地存储管理

如何重新访问Flash内容&#xff1f;CefFlashBrowser实现SWF播放与本地存储管理 【免费下载链接】CefFlashBrowser Flash浏览器 / Flash Browser 项目地址: https://gitcode.com/gh_mirrors/ce/CefFlashBrowser 现代浏览器对Flash技术的支持终止&#xff0c;导致大量教育…

作者头像 李华
网站建设 2026/3/27 5:26:27

新手必看:Hunyuan-MT-7B-WEBUI部署避雷与优化建议

新手必看&#xff1a;Hunyuan-MT-7B-WEBUI部署避雷与优化建议 你兴冲冲点开镜像页面&#xff0c;点击“一键部署”&#xff0c;等了三分钟&#xff0c;浏览器打开却显示“Connection refused”&#xff1b; 你反复检查1键启动.sh权限&#xff0c;确认GPU已识别&#xff0c;可日…

作者头像 李华