news 2026/9/25 2:11:00

C语言详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C语言详解

文章目录

  • 1 . 概要
  • 2 . C语言语法
    • 2.1 关键字解释、
  • 3 . C语言运算符优先级
  • 4 . 本质理解
    • 4.1 内存的本质:数字世界的生命与轮回
    • 4.2 语法的本质:掌控数字宇宙的至高功法
  • 5 . 语法应用
    • 5.1 简单示例
    • 5.2 指针:时空操控的灵魂之术
      • 5.2.1 跨越维度的力量
      • 5.2.2 为何需要指针?时空效率的双重突破
      • 5.2.3 指针的本质:坐标与存在
      • 5.2.4 时空穿梭:*运算符
      • 5.2.5 灵魂出窍:隔空取物的高阶功法
        • 灵魂出窍的哲学意义
      • 5.2.6 指针功法
        • 指针不是C语言的难点,而是精髓所在。初学者看到的可能是语法复杂性,但修行者看到的是时空操控的自由度。当你掌握了指针,你就掌握了:
    • 5.3 C语言结构体:数据封装与内存管理的艺术
      • 引言:为什么需要结构体?
      • 5.3.1 结构体与数组的本质区别
        • 内存布局对比
        • 关键差异:
      • 5.3.2 结构体的专业应用
        • 1. 数据封装与抽象
        • 2. 内存映射与硬件寄存器访问
        • 3. 灵活的内存操作
      • 5.3.3结构体的高级特性
        • 1. 内存对齐与优化
        • 2. 位域:紧凑存储布尔标志
        • 3. 结构体嵌套与数据层次
      • 5.3.4 工程实践建议
        • 1. 命名规范
        • 2. 封装与访问控制
        • 3. 错误处理模式
      • 5.3.5 结论
  • 6 . 编译过程
    • 6.1 预处理
    • 6.2 编译
    • 6.3 汇编
    • 6.4 链接
  • 7 . 小结

【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/127486388


1 . 概要

  • 深入浅出C语言,以下内容简洁,适合入门与加深理解

2 . C语言语法

autobreakcasecharconstcontinuedefaultdo
doubleelseenumexternfloatforgotoif
intlongregisterreturnshortsignedsizeofstatic
structswitchtypedefunionunsignedvoidvolatilewhile

2.1 关键字解释、

  • auto :声明自动变量
  • break:跳出当前循环
  • case:开关语句分支
  • char :声明字符型变量或函数返回值类型
  • const :声明只读变量
  • continue:结束当前循环,开始下一轮循环
  • default:开关语句中的“默认”分支
  • do :循环语句的循环体
  • double :声明双精度浮点型变量或函数返回值类型
  • else :条件语句否定分支(与 if 连用)
  • enum :声明枚举类型
  • extern:声明变量或函数是在其它文件或本文件的其他位置定义
  • float:声明浮点型变量或函数返回值类型
  • for:一种循环语句
  • goto:无条件跳转语句
  • if: 条件语句
  • int: 声明整型变量或函数
  • long :声明长整型变量或函数返回值类型
  • register:声明寄存器变量
  • return :子程序返回语句(可以带参数,也可不带参数)
  • short :声明短整型变量或函数
  • signed:声明有符号类型变量或函数
  • sizeof:计算数据类型或变量长度(即所占字节数)
  • stati` :声明静态变量
  • struct:声明结构体类型
  • switch :用于开关语句
  • typedef:用以给数据类型取别名
  • unsigned:声明无符号类型变量或函数
  • union:声明共用体类型
  • void :声明函数无返回值或无参数,声明无类型指针
  • volatile:说明变量在程序执行中可被隐含地改变
  • while :循环语句的循环条件

3 . C语言运算符优先级

4 . 本质理解

4.1 内存的本质:数字世界的生命与轮回

  • 在C语言的世界里,学习语法之前,我们首先要理解一个最基础也最重要的概念——内存。
  • 想象我们身处的自然界:地球上有70多亿人,每个人都是独特的生命单元。我们从自然中诞生——吸收阳光、空气、水,从自然获取物质构成身体;我们最终又回归自然——生命结束后,身体分解,元素重新进入大自然的循环。
  • 每一块内存单元都像是数字宇宙中的基本粒子
  • 当我们声明一个变量时,我们是在向操作系统申请一小块“自然空间”——这是内存的诞生
  • 当我们为变量赋值时,我们是在用数据为这块空间赋予“生命的意义”
  • 当变量超出作用域或被显式释放时,内存回归系统的“自然状态”——这是内存的回归

4.2 语法的本质:掌控数字宇宙的至高功法

  • 理解了内存的本质,我们站在了数字宇宙的边缘。但仅凭领悟无法成为真正的主宰者——就像理解海洋的广阔,不等于能够驾驭惊涛骇浪。认知与掌控之间,隔着一条名为“功法”的鸿沟。
  • 只有理解规律,才能驾驭万物。只有掌握方法,才能塑造世界。于是,他们倾尽智慧,创出了这部数字世界的至高功法——《C语言》。这不仅仅是一门编程语言,而是一整套掌控内存、塑造现实的道法术器。

5 . 语法应用

5.1 简单示例

intmain(intargc,char*argv[]){unsignedcharvalue=0x01;if(value==0x01){;}return0;}

语法极其简洁,可能有读者不太了解 “ int argc,char* argv[] ”:这里的内容意义,由于C语言是面向过程,系统级,当系统调用一个程序时,可以执行初期给定输入数据,其中前者是数据数量,后者是具体数据

5.2 指针:时空操控的灵魂之术

5.2.1 跨越维度的力量

在C语言的修行之路上,指针是让无数初学者望而生畏,却又让大师们如鱼得水的核心功法。它不是阻碍,而是通往内存主宰之境的必经之门。当我们谈论指针时,我们谈论的是一种跨越时空的操控能力。

5.2.2 为何需要指针?时空效率的双重突破

在数字宇宙中,每一次变量操作都是在时空中留下痕迹。直接操作变量如同每次都要亲临现场:

// 传统方式:亲力亲为intdata=100;// 创造data=data*2;// 修改intbackup=data;// 复制(消耗额外时空)

这种方式的局限显而易见:

  • 时间消耗:大量数据复制需要CPU周期
  • 空间消耗:每个副本占用额外内存
  • 效率瓶颈:难以跨越函数边界传递大型数据

指针的出现,是时空操控的一次革命性突破。

5.2.3 指针的本质:坐标与存在

intreality=42;// 在某个坐标创造存在printf("存在本身: %d\n",reality);// 42printf("存在坐标: %p\n",&reality);// 0x7ffeebd39a9c// &reality 不是值,而是"这里"的坐标// 就像"北京市朝阳区建国门外大街1号"不是建筑本身,而是位置#### 坐标系统:&运算符 每个变量在数字宇宙中都有一个绝对坐标——内存地址。&运算符就是获取这个坐标的钥匙:

5.2.4 时空穿梭:*运算符

拥有坐标后,我们可以跨越时空直接操控。*运算符就是时空穿梭之门:

int*observer=&reality;// 获得坐标,成为观察者printf("坐标指向的存在: %d\n",*observer);// 42*observer=2024;// 无需亲自到场,直接修改printf("修改后的存在: %d\n",reality);// 2024

5.2.5 灵魂出窍:隔空取物的高阶功法

让我们通过一个精妙的示例,体会指针带来的效率革命:

intmain(intargc,char*argv[]){u8*consciousness=NULL;// 意识体,暂时不依附任何存在u8 body=1;// 肉身,初始状态为1consciousness=&body;// 意识出窍,附身于肉身*consciousness=2;// 隔空操控,直接修改肉身状态// 传统方式需要这样检查if(body==1){// 此时body已经是2,无需进入body=2;// 这段代码永远不会执行}return0;}
灵魂出窍的哲学意义

想象一下,你有一个强大的意识体(指针):

  • 没有指针:你需要走到每个人面前,亲口告诉他们该做什么
  • 拥有指针:你的意识可以瞬间附身任何人,直接操控他们的行动

这种效率差异是指数级的!

5.2.6 指针功法

  • 一取地址得坐标,二解引用触本质。
  • 三传指针免复制,四动内存创天地。
  • 五防悬空避崩溃,六置NULL归虚无。
  • 七层递进掌万物,八面玲珑控时空。
    结语:从畏惧到精通
指针不是C语言的难点,而是精髓所在。初学者看到的可能是语法复杂性,但修行者看到的是时空操控的自由度。当你掌握了指针,你就掌握了:
  • 跨越函数边界的操控能力

  • 动态创造和销毁世界的力量

  • 避免不必要数据复制的智慧

  • 构建复杂数据结构的基石

指针,是连接意识与存在的桥梁,是数字宇宙中最高效的沟通方式。 不要畏惧它,而要渴望掌握它。因为当你真正理解指针的那一刻,你就不再是内存的访客,而是它的主宰者。


5.3 C语言结构体:数据封装与内存管理的艺术

引言:为什么需要结构体?

在C语言编程中,当我们需要处理一组逻辑上相关但类型可能不同的数据时,简单的数组显得力不从心。数组要求所有元素类型相同,而现实世界中的数据往往是多元化的。结构体(struct)正是为了解决这一问题而设计的,它允许我们将不同类型的数据组合成一个单一的逻辑单元。

5.3.1 结构体与数组的本质区别

内存布局对比
// 数组:相同类型元素的连续集合u8 array[10];// 10个连续的u8类型内存单元// 结构体:不同类型成员的组合typedefstruct{u8 id;// 1字节u16 value;// 2字节(注意对齐问题)u32 count;// 4字节}SensorData;// 总共可能需要7字节(考虑对齐后可能是8字节)
关键差异:
  • 数组提供同质化数据存储,支持随机访问和迭代
  • 结构体提供异质化数据封装,强调数据之间的逻辑关联性

5.3.2 结构体的专业应用

1. 数据封装与抽象
// 定义学生信息结构体typedefstruct{u32 student_id;// 学号charname[50];// 姓名u8 age;// 年龄floatgpa;// 平均绩点u8 course_count;// 选修课程数}Student;
2. 内存映射与硬件寄存器访问

在嵌入式系统和操作系统开发中,结构体常用于精确映射硬件寄存器:

// 映射串口控制寄存器typedefstruct{volatileu32 DATA;// 数据寄存器volatileu32 STATUS;// 状态寄存器volatileu32 CONTROL;// 控制寄存器volatileu32 BAUD;// 波特率寄存器}UART_Registers;// 定义UART1的寄存器映射#defineUART1_BASE0x40001000UART_Registers*uart1=(UART_Registers*)UART1_BASE;// 直接操作寄存器uart1->BAUD=9600;// 设置波特率uart1->CONTROL|=0x01;// 使能UART
3. 灵活的内存操作

结构体支持指针访问,但需注意类型安全和内存对齐:

typedefstruct{u8 status;// 状态标志u32 data;// 数据值u16 checksum;// 校验和}Packet;Packet packet;intmain(){u8*raw_ptr=NULL;// 获取结构体起始地址raw_ptr=(u8*)&packet;// 通过字节指针操作结构体内容// 注意:这种操作需要了解结构体内存布局和对齐*raw_ptr=0x01;// 设置status字段// 更安全的访问方式是通过结构体成员packet.status=0x01;packet.data=0x12345678;packet.checksum=0xABCD;return0;}

5.3.3结构体的高级特性

1. 内存对齐与优化

编译器会对结构体进行内存对齐以提高访问效率:

// 编译器可能会在成员之间插入填充字节typedefstruct{u8 a;// 1字节// 编译器可能插入3字节填充(在32位系统上)u32 b;// 4字节u16 c;// 2字节// 编译器可能插入2字节填充}UnoptimizedStruct;// 总大小可能为12字节// 优化版本:按大小降序排列减少填充typedefstruct{u32 b;// 4字节u16 c;// 2字节u8 a;// 1字节// 只插入1字节填充}OptimizedStruct;// 总大小可能为8字节
2. 位域:紧凑存储布尔标志
// 使用位域优化存储空间typedefstruct{u8 is_active:1;// 1位:是否激活u8 mode:2;// 2位:模式选择(0-3)u8 priority:3;// 3位:优先级(0-7)u8 reserved:2;// 2位:保留位}DeviceStatus;// 总共1字节
3. 结构体嵌套与数据层次
// 日期结构体typedefstruct{u16 year;u8 month;u8 day;}Date;// 员工信息结构体(嵌套使用)typedefstruct{u32 emp_id;charname[50];Date hire_date;// 嵌套结构体floatsalary;struct{// 匿名结构体:联系信息charphone[15];charemail[50];}contact;}Employee;

5.3.4 工程实践建议

1. 命名规范
  • 使用有意义的名称,避免缩写
  • 结构体类型名使用sPascalCase
  • 结构体变量使用PascalCase或蛇形命名随个人意愿
2. 封装与访问控制
// 头文件声明(public_interface.h)typedefstructDataHandleDataHandle;// 不完全类型,隐藏实现细节// 公共APIDataHandle*create_data_handle(u32 size);voidprocess_data(DataHandle*handle);voiddestroy_data_handle(DataHandle*handle);// 实现文件(private_implementation.c)structDataHandle{// 具体实现对外隐藏u8*buffer;u32 size;u32 capacity;u8 checksum;};
3. 错误处理模式
typedefstruct{interror_code;charerror_msg[100];void*data;size_tdata_size;}OperationResult;OperationResultread_file(constchar*filename){OperationResult result={0};// 执行操作FILE*file=fopen(filename,"rb");if(!file){result.error_code=ERR_FILE_NOT_FOUND;snprintf(result.error_msg,sizeof(result.error_msg),"无法打开文件: %s",filename);returnresult;}// ... 读取文件内容returnresult;}

5.3.5 结论

结构体是C语言中实现数据封装和抽象的核心机制。它不仅解决了异质数据集合的管理问题,还通过内存对齐、位域等特性提供了精细的内存控制。在大型工程中,合理使用结构体能够:

  • 提高代码可读性:通过有意义的成员名称代替晦涩的数组索引
  • 增强类型安全:编译器能够检查结构体成员的类型正确性
  • 简化维护:相关数据的修改被限制在结构体定义范围内
  • 优化内存访问:合理对齐可以显著提升CPU缓存效率
  • 支持复杂数据结构:为链表、树、图等数据结构奠定基础

正如生物体由不同类型的细胞有序组成,良好的软件结构也需要将相关数据高内聚地组织在一起。结构体正是实现这一目标的关键工具,它让C语言在保持底层控制能力的同时,具备了构建复杂系统的表达能力。


6 . 编译过程

6.1 预处理

#definemacro0x01voidfunc(){unsignedcharx=macro;}

预处理阶段时把宏macro替换为0x01

6.2 编译

unsignedcharx=macro;
MOVS r0, #0x01

编译阶段把C语言转换成汇编内容, 因为这里在局部变量因此被分配到缓存寄存器R0

6.3 汇编

MOVS R0, #0x01

0x2001 汇编阶段把汇编指令根据当前平台转换成机器码

6.4 链接

程序中N条汇编机器码需要整合在一起,此时把这些机器码链接在一块输出最终可执行文件


编译过程大致如此,【Q】最终可执行文件为什么可以执行?【A】计算机最终执行权是CPU,CPU按照Flash或RAM区域地址逐步执行,而当可执行文件存到Flash或RAM区域,CPU就会根据可执行文件的内容逐步执行,这里讲解一个例子,例如当我在桌面GUI右击一下鼠标,为什么桌面会弹窗出来,步骤是这样,鼠标机械动作触发了电信号,经过USB协议与电脑主板通信,电脑主板把收到的数据反馈给CPU,由于加载了系统,系统层面会接收到鼠标这种HID设备事件,系统事件循环触发系统GUI已定逻辑,显存加载弹窗的数据,系统界面弹窗,这一切都是因为电脑系统已经集成了逻辑,这个系统逻辑就是用C语言逐步写出来的,也是经过了上述编译四个过程得出的程序

7 . 小结

学习C语言平时用C free,VS等软件验证程序,若中途学习感到困惑有阻碍,不必忧心,多看多写,自然就明白了其中的逻辑,另不必刻意背运算优先级,写着自然就记住了,印象模糊时来回顾一遍运算优先级,看到这里,相信大家已经入门。

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

QT版本Tcp通信实战:QTcpSocket/QTcpServer、粘包处理与断线重连

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:07:29

Neo4j 5.26.0 Windows免安装配置全攻略:从zip解压到稳定运行

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:06:56

ESP32-S3 Flash与PSRAM配置实战:从PlatformIO到Octal PSRAM

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:05:01

STM32 SBUS协议解析:DMA循环接收+IDLE中断+状态机,稳定不丢帧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 2:04:18

USBKey证书失败真相:从设备管理器到信任链的七层诊断

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华