星光编译者· 个人主页 学习专栏《C/C 成长笔记》·《Linux 实践手册》·《数据结构与算法》 向云端飞扬编译属于自己的代码星河。☕ 写在开篇你好这里是星光编译者。这里记录我在C/C、Linux、数据结构与算法学习中遇到的真实问题、亲手验证过的代码以及那些容易被忽略的实现细节。比起简单罗列结论我更愿意从问题出发把一个知识点的来由讲清楚把“为什么会这样”和“应该怎样解决”说明白让每一次踩坑都沉淀成可以复用的经验。如果这篇记录能帮你少绕一点路或让某个模糊的地方忽然变得清晰那么这次分享便有了意义。愿我们在一次次阅读、编译与调试中稳步向前慢慢搭起属于自己的技术世界。本文定位从“变量放在哪里”出发建立地址、指针变量和解引用的完整联系再读懂指针类型、void *与const的真正含义。学习目标会用取地址、用*间接访问对象知道指针大小和指针类型是两件事能读准const int *、int * const与const int * const。阅读说明根据课程 PDF《第11讲深入理解指针(1)》第 14 节整理。本文按 C11 规则补充边界示例地址只用于说明实际运行值由环境决定。文章目录一、内存与地址先给每个字节编号二、取地址与指针变量三、解引用通过地址找到对象四、指针变量的大小五、指针类型到底决定什么六、void 指针能接收地址不代表能直接使用七、const 修饰指针分清“指向谁”和“改什么”八、常见误区、高频问答与练习总结一、内存与地址先给每个字节编号课程用宿舍房间类比内存房间如果没有门牌号找人就只能挨间搜索有了101、102、201这样的编号就能直接定位。计算机内存也要解决同样的问题。在 C 语言的抽象模型中内存可以理解成一系列可定位的字节1 byte sizeof(char)而且sizeof(char)永远等于1一个字节有多少位由CHAR_BIT给出常见平台是 8 位每个可定位的存储位置都有地址CPU 和内存硬件依靠地址、数据等信息协同工作。#includelimits.h#includestdio.hintmain(void){printf(CHAR_BIT %d\n,CHAR_BIT);printf(sizeof(int) %zu\n,sizeof(int));return0;}如果某个int对象占 4 字节它会覆盖 4 个连续字节位置。程序一般用该对象的起始地址来标识它不需要手工记住每个字节的编号。一句话建立直觉变量是带类型的对象地址用来定位对象指针则是 C 语言中表示地址的值。二、取地址与指针变量定义一个变量就会为对象准备存储空间用取地址操作符可以得到它的地址。#includestdio.hintmain(void){intvalue10;int*pointervalue;printf(value %d\n,value);printf(address %p\n,(void*)value);printf(pointer %p\n,(void*)pointer);return0;}这里有三个角色表达式含义类型value整型对象本身intvaluevalue的地址int *pointer保存了该地址的指针变量int *int *pointer的拆解方式是pointer是变量名*表示它是指针int表示它指向的对象类型是int。相应地char *指向chardouble *指向double。打印地址要使用%p对应的参数应传void *因此上面显式转换为(void *)。不要用%d、%x去猜地址的宽度。三、解引用通过地址找到对象保存地址的目的是后续使用。一元*称为间接运算符或解引用操作符*pointer表示通过pointer中的地址访问它所指的对象。#includestdio.hintmain(void){intvalue100;int*pointervalue;*pointer0;printf(%d\n,value);/* 0 */return0;}关键不是“pointer变成了value”而是*pointer指定了那个被指向的int对象。修改*pointer就是修改该对象。但是一个指针“存着一个数值”并不等于“它可以被解引用”。在*pointer之前至少要确认指针指向一个生存期仍然有效的对象指针满足目标类型的对齐和访问规则访问没有越过对象边界指针不是空指针。四、指针变量的大小课程用 32 位与 64 位平台说明指针大小在常见实现中32 位平台的数据指针常见为 4 字节64 位平台常见为 8 字节。这是常见现象不应写成脱离实现的语言定律。#includestdio.hintmain(void){printf(char * : %zu\n,sizeof(char*));printf(short * : %zu\n,sizeof(short*));printf(int * : %zu\n,sizeof(int*));printf(double * : %zu\n,sizeof(double*));return0;}sizeof的结果类型是size_t用%zu输出。在大多数通用平台上上述几种对象指针的大小相同但最可靠的做法仍然是在当前编译目标上使用sizeof不把某个结果硬编码进程序。指针大小也不等于所指对象大小。在某个常见 64 位环境中sizeof(char *)、sizeof(int *)和sizeof(double *)可能都是8但sizeof(char)、sizeof(int)与sizeof(double)往往不同。前者回答“地址这个值用多少字节保存”后者回答“目标类型的对象占多少字节”。另外程序每次运行时打印的具体地址可能不同。写逻辑时应依赖“这个指针指向哪个对象”不应依赖某次调试里偶然观察到的地址数字。小结指针变量需要多大空间主要是平台实现问题指针指向什么类型则决定程序如何解释和移动这个指针。五、指针类型到底决定什么“同一平台上指针大小常常相同”不意味着char *、int *、double *可以混着用。指针类型至少影响两件核心事情。5.1 解引用时访问什么类型的对象intnumber0x11223344;int*integer_pointernumber;*integer_pointer0;*integer_pointer是int左值赋值会把整个number设为0。如果要观察对象的逐字节表示应使用unsigned char *#includestddef.h#includestdio.hintmain(void){intnumber0x11223344;constunsignedchar*bytes(constunsignedchar*)number;for(size_tindex0;indexsizeof(number);index){printf(%02X ,(unsignedint)bytes[index]);}putchar(\n);return0;}输出顺序受字节序等实现细节影响不应预设某一台机器的结果就是语言唯一规则。5.2 指针加减整数时跨过多少个字节pointer 1不是简单把地址数值加1它表示前进到“下一个所指类型的元素”。charchar_array[4]{0};intint_array[4]{0};char*characterchar_array[0];int*integerint_array[0];printf(%td\n,(character1)-character);/* 1 个 char 元素 */printf(%td\n,(integer1)-integer);/* 1 个 int 元素 */两个差都是1因为指针相减得到的是元素间隔数不是字节数。底层地址跨度分别对应sizeof(char)与sizeof(int)。这些运算只有在语言规则允许的对象边界内才有意义。下篇会专门讲指针与数组、指针相减和关系运算。六、void *指针能接收地址不代表能直接使用void *是“指向未指定对象类型”的指针。在 C 中对象指针可以转换为void *也可以从void *转回相应的对象指针类型。intnumber10;doubledecimal3.14;void*genericnumber;genericdecimal;但void没有对象大小程序不知道应当把*generic解释成什么也不知道generic 1应该前进多少。因此标准 C 中不能直接解引用void *也不能对它做指针算术。void*genericnumber;/* 先还原成正确类型再解引用 */int*integer_pointergeneric;printf(%d\n,*integer_pointer);malloc、qsort、回调上下文等泛型接口常用void *。它提供的是“类型中立的传递通道”不是“可以忽略类型规则”的许可证。七、const修饰指针分清“指向谁”和“改什么”const最容易在指针声明里读反。一个实用方法是从变量名向外读先看星号两边的限制。声明能否通过指针改对象指针能否改指向int *pointer能能const int *pointer不能能int * const pointer能不能const int * const pointer不能不能7.1 指向const int的指针intfirst10;intsecond20;constint*pointerfirst;/* *pointer 99; *//* 错误不能通过 pointer 修改 */pointersecond;/* 正确pointer 可以改指向 */const int *和int const *含义相同。它限制的是“通过这条指针路径去修改int”不一定表示对象本身永远不变。如果原对象是普通int仍可以通过其他允许修改的名称改变它。7.2 指针本身是constintfirst10;intsecond20;int*constpointerfirst;*pointer99;/* 正确可以修改 first *//* pointer second; *//* 错误指向不能改 */因为pointer本身不能重新赋值它必须在定义时初始化。7.3 两边都限制intfirst10;constint*constpointerfirst;既不能通过pointer修改first也不能让pointer改指别处。7.4 在函数接口中用const表达“只读”如果函数只需要读取数组不应通过参数修改元素就可以把形参写成指向const的指针#includestddef.hlongsum_array(constint*values,size_tlength){longsum0;for(size_tindex0;indexlength;index){sumvalues[index];}returnsum;}这样写不会让指针自动变安全values仍须指向至少包含length个int的有效区间。它表达的是接口的修改意图让编译器阻止函数内部的意外写入。还要特别修正一个常见误解constintvalue10;int*pointer(int*)value;*pointer20;/* 未定义行为 */强制转换只是压低了类型系统的诊断不会把一个真正定义为const的对象变成可修改对象。八、常见误区、高频问答与练习8.1 常见误区误区正确理解指针就是指针变量指针是地址值指针变量是保存指针的对象得到变量的“值”得到对象地址指针有值就能*还要检查指向、生存期、边界、类型与对齐指针类型只是写给编译器看它决定解引用类型和指针算术的步长void *可以直接读写任意数据它要先转回正确对象指针类型强转可以解除const修改真正的const对象是未定义行为8.2 高频问答Q1int* p和int *p哪个正确两者语法含义相同。但不要写int* first, second;然后误以为两者都是指针这里只有first是指针second是int。建议每行声明一个变量。Q2指针大小与它指向的类型完全无关吗在常见平台上各种对象指针大小通常相同但 C 代码不应把这种常见实现写死成跨平台前提。需要大小时用sizeof。Q3const int *p是不是表示对象永远不能改不一定。它表示不能通过p去修改所指int。如果原对象不是const可能仍然通过其他合法路径修改。Q4声明里的*和表达式里的*是同一个用法吗不是。int *pointer;中的*参与声明说明pointer是指向int的指针*pointer 10;中的*是一元间接运算符用于访问所指对象。符号相同语法位置和角色不同。8.3 动手练习声明一个double变量和指向它的指针用指针把值改为6.25。分别解释char *p、const char *p、char * const p、const char * const p。用%p打印一个对象地址说明为什么要转为void *。解释为什么标准 C 中不能直接写void_pointer 1。将“解引用前的四项检查”用自己的话复述一遍。总结指针基础可以压缩成一条主线**对象占据存储空间得到对象地址指针变量保存地址*再通过地址访问对象。**指针类型告诉编译器如何解释目标和如何跨元素移动const则把“能不能改指向”与“能不能通过指针改对象”分开表达。下篇将把这些基础放进真正的程序场景数组遍历、指针相减、野指针规避、assert断言、模拟strlen以及用地址交换两个整数。资料课程 PDF《第11讲深入理解指针(1)》ISO C11 工作草案 N1570 的声明、指针、转换与表达式条款。本文示例和示意图为重新整理与绘制。
企业数字化 ERP 产品动态
相关推荐
数字员工要来了,你的工厂准备好了么? 接触了不少制造业老板,发现一个有意思的现象:大家都在聊AI,但焦虑点都不一样。有的老板看了场发布会就来问我:"你们系统能不能接大模型?我们也要上数字员工。"有的老板刷到短视频就慌了:"听… · 2026/9/27 22:50:55
C语言分支语句全攻略:if 与 switch 从入门到实战 C语言学习记录
日期: 8.11
C语言是结构化的程序设计语言
顺序结构选择结构循环结构
📖今日知识点 ——if语句
语法结构:if(表达式)语句;if(表达式)语句1;else语句2&#… · 2026/9/27 22:50:55
第 22-3 篇:vllm_mgr.py——进程守护与看门狗 上一篇:22-2《/admin API——状态、配置、加载、转换》| 下一篇:23-1《国密 SM3——KAT 红线先于实现》
只读验证篇:本文仅板端 --help/status 只读实测;未对运行中的引擎演示 start/stop/kill(诚实边界见… · 2026/9/27 22:50:49
南方医科大学精品课程建设网站域名选型对比评测 南方医科大学精品课程建设网站域名选型对比评测 域名服务器搞不懂,是卡在南方医科大学精品课程建设网站上线前的最大拦路虎。很多老师拿到学校任务,第一反应是找个建站公司,结果被各种技术名词绕晕:什么DNS、SSL、备案,听得一头雾水。今天不聊虚的… · 2026/9/28 0:01:01
建设网站北京市进阶技巧 北京建设网站选错技术栈,流量归零?3个对比评测帮你避坑 网站做好了没人访问,比没做还让人焦虑。很多北京本地的站长,明明代码写得漂亮,UI也在线,结果上线一个月,百度收录寥寥无几,自然流量几乎为零。这时候再回头找开发团队,对方只会甩锅说“内容… · 2026/9/28 0:01:01
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19
制作网页比较方便的软件怎么选?一文搞懂避坑指南 制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06
MATLAB雷达信号脉冲压缩仿真:LFM线性调频、匹配滤波与距离分辨率实现 简介:这套Matlab仿真工具完整呈现雷达信号脉冲压缩过程,从线性调频(LFM)信号生成、目标回波仿真到匹配滤波压缩处理均有可运行代码支撑,面向电子信息工程、计算机、数学等专业学生,适用于课程设计、期末大作… · 2026/9/27 0:00:01
汕头网站建设制作厂家避坑指南:5大注意事项救急 汕头网站建设制作厂家避坑指南:5大注意事项救急 改个需求建站公司拖一周,这种憋屈事我见得太多了。 很多汕头老板找本地建站团队,签合同前看着方案挺美,一上线就变脸。 今天不聊虚的,直接拆解找 汕头网站建设制作厂家 时的5个核心 注意事项… · 2026/9/27 0:00:01
多模态虚假新闻检测实战:BERT+ResNet双塔与对比学习 简介:基于PyTorch的多模态虚假新闻检测项目完整代码包,面向自然语言处理与计算机视觉交叉方向的开发者、科研人员及毕业设计选题者,解决社交媒体中文本与图像联合识别虚假新闻的问题。系统以BERT预训练模型提取文本语义特征,以Res… · 2026/9/27 0:00:01
制作网页比较方便的软件怎么选?一文搞懂避坑指南 制作网页比较方便的软件怎么选?一文搞懂避坑指南 很多老板一上来就问:做个网站多少钱?但我反问他:你的域名买了吗?服务器租了吗?他一脸懵。这就是典型的“域名服务器搞不懂”。别急,今天咱们不聊虚的,直接 一文搞懂 那些让你头秃的技术名词。… · 2026/9/28 0:00:06
婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 婚恋网站实战案例:避开3个高价坑,省钱50%还能跑赢流量 找婚恋网站建站公司,最怕的就是被坑高价。很多同行跟我吐槽,报价单上写得模棱两可,功能栏里全是“高级定制”、“专属UI”,结果落地全是套壳。今天不聊虚的,直接甩几个我经手的 实战案例… · 2026/9/28 0:00:19
济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 济南做网站多少钱:3个案例拆解,防黑源码下载全攻略 上周济南一个做建材的老板找我,脸都绿了。他的官网首页弹出了赌博广告,后台被植入了挖矿脚本。他慌得问我:“网站被黑挂马不知道怎么办?能不能直接找之前的外包公司要源码下载,看看哪里被动了手脚?… · 2026/9/28 0:00:25