news 2026/5/5 6:52:43

C语言指针深入浅出1

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言指针深入浅出1

目录

  • 1.内存和地址
    • 1.1 内存
    • 1.2 对编址的理解
  • 2.指针变量和地址
    • 2.1 取地址操作符(&)
    • 2.2 指针变量和解引用操作符(*)
      • 2.2.1 指针变量
      • 2.2.2 拆解指针类型
      • 2.2.3 解引用操作符
    • 2.3 指针变量的大小
  • 3. 指针变量类型的意义
    • 3.1 指针的解引用
    • 3.2 指针+ -整数
  • 3.3 void* 指针
  • 4. 指针运算
    • 4.1 指针 + - 整数
    • 4.2 指针 - 指针
    • 4.3 指针的关系运算

1.内存和地址

1.1 内存

说起内存,我们可以举一个生活例子,用宿舍楼找房间的例子。
在一栋有很多房间的宿舍楼里,如果房间没有编号,找人就只能一间一间找,效率很低。为了更快找到目标房间,可以按照楼层给房间编号,例如:

一楼:101、102、103……
二楼:201、202、203……

这样一来,只要知道房间号,就能快速定位房间。

对应到计算机中:

宿舍楼可以理解为内存,
房间可以理解为内存中的存储单元,
房间号就相当于内存地址。

所以,内存地址的作用就是帮助计算机快速找到数据存放的位置

对应到计算机中,计算机上的CPU(中央处理器)在处理数据时,需要的数据是放在内存中读取的,处理后的数据是放在内存中读取的,电脑的内存一般是8GB/16GB/32GB等,电脑将内存划分为一个一个的内存单元,每个内存单元的大小取1个字节
注意:一个比特位可以存储一个二进制位的位1或者0

1Byte=8bit1KB=1024Byte1MB=1024KB1GB=1024MB1TB=1024GB1PB=1024TB

每个内存单元就像一个学生宿舍,里面可以存放数据。

一个字节8 个比特位,就像一个宿舍住 8 个人,每个人代表 1 个比特位。

每个内存单元都有一个编号,这个编号就像宿舍门牌号。CPU 通过这个编号,就能快速找到对应的内存位置。

在计算机中,内存单元的编号叫做地址
在 C 语言中,地址又叫做指针
内存地址的编号,地址,指针三者之间等价。


1.2 对编址的理解

对编址的理解,要先理解,在计算机内有许多的硬件单元,硬件单元是要互相协同工作的,相互之间能够进行数据传递,计算机中用线连起来,对编址的理解就要了解地址总线
CPU 访问内存时,会先给出一个地址。内存根据这个地址找到对应位置,再把数据交给 CPU。
地址是通过地址总线传递的。
地址总线由多根线组成,每根线只能表示0 或 1
如果有 32 根地址线,就可以表示:232个不同地址
也就是说,CPU 最多可以找到 232个内存单元。
编址就是给内存中的每个存储单元分配一个唯一编号
如果实在不理解,看下图:


2.指针变量和地址

2.1 取地址操作符(&)

在C语言中,变量创建的本质就是向内存中申请空间。

上述代码中,创建了整型变量a, 向内存中申请了4个字节,用来存放整数10,每个字节都有地址。


上述的代码就是创建了整型变量a,内存中申请4个字节,⽤于存放整数10,其中每个字节都有地址,上图中4个字节的地址分别是:

//因为是在X64平台下,所以有16位,如果在X86平台下,就是8位0x0000003C588FF8C40x0000003C588FF8C80x0000003C588FF8CC0x0000003C588FF8D0

讲解了这么多,要想得到a的地址,就要学习取地址操作符(&)

intmain(){inta=11;&a;//& -> 取出a的地址printf("%p\n",&a);return0;}

&a 取出的是a所占4个字节中地址较小的字节的地址,虽然整型占4个字节,我们只需知道第一个字节,顺藤摸瓜访问就可以访问到4个字节的数据。


2.2 指针变量和解引用操作符(*)

2.2.1 指针变量

我们通过取地址操作符(&)拿到变量的地址是一个数值,这个数值有时候是需要存储起来的,方便后期进行使用,我们就可以将地址存放在指针变量中。
例如:

intmain(){inta=10;int*pa=&a;//取出a的地址并存储到指针变量pa中return0;}

指针变量也是一种变量 , 指针变量是用来存放地址的,存放在指针变量中的值都会理解成地址。

2.2.2 拆解指针类型

指针变量pa的类型是int*,我们应该这样来理解指针变量:

2.2.3 解引用操作符

我们将地址通过指针变量保存起来,要通过解引用操作符*来进行访问。解引用操作符*的作用是:通过指针中保存的地址,找到该地址对应的变量。


2.3 指针变量的大小

指针变量是用来存放地址的,地址有多大,指针变量就需要多大的空间。
32 位平台指针大小通常是4 字节64 位平台指针大小通常是8 字节


结论:

  • 32位平台下(X86)环境下地址是32个bit位,指针变量的大小是4个字节
  • 64位平台下(X64)环境下地址是64个bit位,指针变量的大小是8个字节
  • 注意:指针变量的大小和类型是无关的,只要是指针类型的变量,在相同平台下,大小都是相同的。

3. 指针变量类型的意义

3.1 指针的解引用

//代码1intmain(){inta=0x11223344;int*pa=&a;*pa=0;return0;}//代码2intmain(){inta=0x11223344;char*pa=&a;*pa=0;return0;}



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


3.2 指针+ -整数

intmain(){inta=0x11223344;int*pa=&a;char*pc=&a;printf("pa = %p\n",pa);printf("pa + 1 = %p\n",pa+1);printf("pc = %p\n",pc);printf("pc + 1 = %p\n",pc+1);return0;}


结论:指针类型决定了指针向前一步或者向后一步走多大(步长)

3.3 void* 指针

void*指针就是一种"通用指针",他可以保存任意类型变量的地址,例如:int、char、float,可以理解为无意义的指针(或者叫泛型指针),但是,void*类型的指针不能直接运算或取值,使用前要先转成具体类型指针。

intmain(){inta=10;int*p=&a;char*pa=&a;return0;}


上述代码中,将⼀个int类型的变量的地址赋值给⼀个char*类型的指针变量。编译器给出了⼀个警
告,是因为类型不兼容,如果使用void*就没问题。

下面一段代码:

intmain(){inta=10;charb='w';int*p=&a;void*pa=&a;void*pb=&b;&pa=100;&pb='x';return0;}

VS编译代码的结果:

从上述中我们可以看到,void*类型的指针可以接受不同的地址,但是不能直接进行指针的运算。
一般void*类型的指针是使用在函数参数的部分,用来接收不同数据的地址,这样的设计可以实现泛型编程的效果,使得一个含函数用来处理多个数据。


4. 指针运算

指针运算一般分为三种,分别是:

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

4.1 指针 + - 整数

这里需要回顾一下数组的知识点,如果忘记的话点击链接就能跳转了:深入浅出数组。
数组在内存中是连续存放的,只要知道第一个元素的地址,顺藤摸瓜就能找到后面的所有元素。

intarr[10]={1,2,3,4,5,6,7,8,9,10};

//第一种写法intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};int*p=&arr[0];//指针变量p取数组arr中的首元素for(inti=0;i<10;i++){printf("%d ",*(p+i));//*(p + i) 就是指针变量指向数组下标为i所对应元素的地址}return0;}//第二种写法intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};int*p=&arr[0];//指针变量p取数组arr中的首元素for(inti=0;i<10;i++){printf("%d ",*p);//先打印p所指向对象的指针p++;//p = p + 1}return0;}


4.2 指针 - 指针

指针减指针得到的是指针与指针之间元素的个数。也可以换一种方式来理解,就是指针 + - 一个整数得到的还是指针,将指针放在等号的同一边,就变成了指针减指针。前提:两个指针指向同一块空间。

intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};printf("%d\n",&arr[9]-&arr[0]);return0;}


介绍完指针减指针之后,我们来模拟实现一下strlen函数。
回顾一下strlen函数,相关介绍:strlen

size_tmy_strlen(char*p){char*start=&p[0];//存储数组首元素的地址while(*p!='\0')//当指针变量指到\0时,循环结束p++;returnp-start;//指针减指针}intmain(){charstr[20]="abcdef";// [a b c d e f \0]size_tlen=my_strlen(str);//传数组名,传的就是数组的地址printf("%zu\n",len);}

我在配合一张图片,让知识理解的更深。


4.3 指针的关系运算

常见的关系运算有以下操作符:

>>=<<===!=

指针就是地址,地址就是内存单元的编号,编号是一个数值,随着下的标增长,地址是由小到大变化的, 所以指针与指针之间可以用来进行关系比较。

intmain(){intarr[]={1,2,3,4,5,6,7,8,9,10};int*p=arr;//将数组的地址存给指针变量pintsz=sizeof(arr)/sizeof(arr[0]);//计算的是数组的大小//注意:因为数组在内存中是连续存放的,所以&arr[sz]编译不会报错,因为在内存中arr[sz]//的地址是已经存在的如果是直接使用arr[sz],不加取地址操作符,就构成了越界访问while(p<&arr[sz])//运用了指针的关系运算{printf("%d ",*p);p++;}return0;}

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

音频扩散模型的控制优化与工程实践

1. 音频扩散模型的核心挑战音频生成领域近年来最引人注目的突破莫过于扩散模型的应用。与传统GAN或VAE相比&#xff0c;扩散模型在生成质量上展现出明显优势&#xff0c;但同时也带来了新的控制难题。我在实际项目中发现&#xff0c;当扩散步数超过100步时&#xff0c;模型行为…

作者头像 李华
网站建设 2026/5/5 6:48:30

ComfyUI-Impact-Pack:解锁AI图像增强的终极工具箱

ComfyUI-Impact-Pack&#xff1a;解锁AI图像增强的终极工具箱 【免费下载链接】ComfyUI-Impact-Pack Custom nodes pack for ComfyUI This custom node helps to conveniently enhance images through Detector, Detailer, Upscaler, Pipe, and more. 项目地址: https://gitc…

作者头像 李华
网站建设 2026/5/5 6:47:15

OpenAI多账户代理OpenClaw:突破API限制,实现负载均衡与成本隔离

1. 项目概述与核心价值最近在折腾AI应用开发的朋友&#xff0c;估计都绕不开一个头疼的问题&#xff1a;OpenAI的API调用限制。无论是个人开发者想低成本测试多个模型&#xff0c;还是小团队需要为不同客户、不同业务线隔离计费和调用&#xff0c;单账号的配额和并发限制都显得…

作者头像 李华
网站建设 2026/5/5 6:47:12

动力电池包膜控制系统设计及放卷张力PLC【附代码】

✅ 博主简介&#xff1a;擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导&#xff0c;毕业论文、期刊论文经验交流。 ✅ 如需沟通交流&#xff0c;扫描文章底部二维码。&#xff08;1&#xff09;基于微分平坦的张力规划与动态前馈补偿&#xff1a;为解决动…

作者头像 李华
网站建设 2026/5/5 6:46:26

有效提升SEO效果的长尾关键词优化实用技巧分享

在本篇文章中&#xff0c;我们将深入探讨长尾关键词的优化技巧&#xff0c;帮助SEO从业者和新手实现搜索引擎排名的提升。文章内容包括长尾关键词的选择、运用和实战技巧&#xff0c;逐步引导读者如何借助数据分析来优化其使用&#xff0c;以提升网页访问量。此外&#xff0c;还…

作者头像 李华