C语言笔记(第n版):知识清单
注:本文参考自【C reference - cppreference.com】和【C 语言参考 | Microsoft Learn】,颇有点借花献佛的意味……
C 程序是一系列包含声明的文本文件(通常为头文件和源文件)的序列。它们经过转换成为可执行程序,当操作系统调用其主函数时执行(除非它本身就是操作系统或另一个独立程序,在这种情况下入口点由实现定义)。在 C 程序中,某些词具有特殊含义,即关键字。其他词可用作标识符,可用于标识对象、函数、结构体、联合体、枚举标签、它们的成员、类型定义(typedef)名称、标签或宏。每个标识符(除宏外)仅在程序的一部分(称为其作用域)内有效,并属于四种命名空间之一。一些标识符具有链接性,这使得它们在不同的作用域或翻译单元中出现时指向相同的实体。函数的定义包括语句和声明的序列,其中一些包含表达式,这些表达式指定了程序要执行的计算。声明和表达式创建、销毁、访问和操作对象。C 语言中的每个对象、函数和表达式都与一种类型相关联。
一、基本概念
Basic concepts - cppreference.com
(一)翻译阶段
Phases of translation - cppreference.com
C源文件经编译器处理,依次经历以下阶段,实际由具体实现决定
- Phase 1 的处理:将源文件字节映射到源字符集的字符,替换特定符号,处理三字符序列。
- Phase 2 的操作:处理行拼接和换行符,明确了非空源文件结束时的要求。
- Phase 3 的分解:将源文件分解为注释、空格序列和预处理令牌,并对注释进行替换处理。
- Phase 4 的包含文件处理:对 #include 引入的文件进行递归的 1 至 4 阶段处理,并在阶段结束时移除所有预处理指令。
- Phase 5 的字符转换:将字符常量和字符串字面量中的字符和转义序列从源字符集转换到执行字符集。
- Phase 6 的字符串拼接:对相邻字符串字面量进行拼接。
- Phase 7 的编译:对令牌进行语法和语义分析及翻译。
- Phase 8 的链接:收集翻译单元和库组件,形成包含执行所需信息的程序图像。
(二)标点符号
| 序号 | 符号 | 描述或用途 |
| 1 |
| 结构体或联合体定义中的声明列表,复合语句的界定,初始化中的初始化器。 |
| 2 |
| 下标运算符,数组声明,C99 起在初始化中引入数组元素的设计符,C23 起属性说明符的界定。 |
| 3 |
| 引入预处理指令,字符串化预处理运算符。 |
| 4 |
| 标记粘贴预处理运算符。 |
| 5 |
| 表达式中的分组指示,函数调用, |
| 6 |
| 语句结束,声明或结构声明列表的分隔。 |
| 7 |
| 条件运算符的一部分,标签声明,位字段成员声明中引入宽度,C23 起枚举基的引入。 |
| 8 |
| 函数声明中的可变参数,C99 起宏定义中的可变参数宏。 |
| 9 |
| 条件运算符的一部分。 |
| 10 |
| C23 起属性的作用域指示,预处理器前缀参数的作用域指示。 |
| 11 |
| 成员访问运算符,C99 起初始化中的结构体/联合体成员的设计符。 |
| 12 |
| 成员访问运算符。 |
| 13 |
| 一元补运算符(位非运算符)。 |
| 14 |
| 逻辑非运算符。 |
| 15 |
| 一元加运算符,二元加运算符。 |
| 16 |
| 一元减运算符,二元减运算符。 |
| 17 |
| 间接运算符,乘法运算符,指针运算符,C99 起函数声明中可变长数组的长度占位符。 |
| 18 |
| 除法运算符。 |
| 19 |
| 模运算符。 |
| 20 |
| 位异或运算符。 |
| 21 |
| 地址运算符,位与运算符。 |
| 22 | | | 位或运算符 |
| 23 |
| 简单赋值运算符,初始化中的对象和初始化器列表的界定,枚举定义中的枚举常量值的引入。 |
| 24 |
| 复合赋值运算符。 |
| 25 |
| 复合赋值运算符。 |
| 26 |
| 复合赋值运算符。 |
| 27 |
| 复合赋值运算符。 |
| 28 |
| 复合赋值运算符。 |
| 29 |
| 复合赋值运算符。 |
| 30 |
| 复合赋值运算符。 |
| 31 |
| 复合赋值运算符。 |
| 32 |
| 等式运算符。 |
| 33 |
| 不等式运算符。 |
| 34 |
| 小于运算符,C23 起 |
| 35 |
| 大于运算符,C23 起上述指令和表达式中头文件名的结束。 |
| 36 |
| 小于等于运算符。 |
| 37 |
| 大于等于运算符。 |
| 38 |
| 逻辑与运算符。 |
| 39 |
| 逻辑或运算符。 |
| 40 |
| 位左移运算符。 |
| 41 |
| 位右移运算符。 |
| 42 |
| 位左移赋值运算符。 |
| 43 |
| 位右移赋值运算符。 |
| 44 |
| 递增运算符。 |
| 45 |
| 递减运算符。 |
| 46 |
| 逗号运算符,用于分隔声明列表、初始化器列表、函数调用参数列表、枚举器列表、宏参数列表、属性列表等。 |
(三)标识符
Identifier - cppreference.com
- 标识符的定义:是由数字、下划线、大小写拉丁字母和特定的 Unicode 字符组成的任意长序列,需以非数字字符开头,且区分大小写,必须符合标准化形式 C。
- 保留标识符:如关键字、以特定格式开头的外部标识符、标准库定义的外部标识符等均为保留标识符,在程序中不能声明使用。
- 潜在保留标识符:包括函数名、typedef 名、宏名、枚举常量等多种类型,它们可能在未来被使用。
- 翻译限制:虽然标识符长度无具体限制,但早期编译器和链接器对标识符有初始字符数量和数量等方面的限制,C 语言标准规定了一些最低支持的限制。
(四)作用域
Scope - cppreference.com
在 C 程序中出现的每个标识符仅在源代码中被称为其作用域的某些可能不连续的部分可见(即可以被使用)。在一个作用域内,只有当实体处于不同的命名空间时,一个标识符才可以表示多个实体
- C 语言有四种作用域:包括块作用域、文件作用域、函数作用域、函数原型作用域。
- 块作用域的规则:在复合语句、函数体、特定表达式和语句内声明的标识符,其作用域从声明点开始到所在块或语句结束。C99 之前,选择和迭代语句自身无块作用域。默认情况下,块作用域变量无链接且自动存储。
- 文件作用域的特性:在任何块或参数列表之外声明的标识符,其作用域从声明点开始到翻译单元结束。文件作用域标识符默认具有外部链接和静态存储。
- 函数作用域:从函数定义开始,到函数块结束而结束。函数内声明的标签且只有标签在函数内任何地方、嵌套块等都有效。
- 函数原型作用域:在函数声明的参数列表中引入的名称的作用域在函数声明符结束时结束。
- 其他作用域规则:结构体、联合体和枚举标签以及枚举常量的作用域有特定的起始点。标识符的作用域通常在声明符结束和初始化器之前开始。
- 嵌套作用域:如果两个由相同标识符命名的不同实体同时处于作用域内,并且它们属于相同的命名空间,那么这些作用域就是嵌套的(不允许有其他形式的作用域重叠),并且出现在内部作用域中的声明会隐藏外部作用域中的声明。
(五)生存期
Lifetime - cppreference.com
在C语言中,对象的生命周期是指对象存在于内存中的时间段,在此期间它可以被程序访问和修改。生命周期的开始和结束时间取决于对象的存储类型。
对象的生命周期定义
- 生命周期: 在这个时间段内,对象保持其地址不变,并且保留其最后一次有效存储的值(除非该值由于某种原因变得不确定)。对于可变长数组(VLA),它还保留其大小。
- 可变长数组 (VLA): 这种类型的数组是在运行时确定其大小的数组。自C99标准以来,VLA成为C语言的一部分。
存储期限与生命周期的关系
- 自动存储期限: 这类对象通常是在函数调用时创建的局部变量。它们的生命周期从进入作用域开始,到离开作用域结束。
- 静态存储期限: 静态变量在整个程序执行期间都存在。它们在程序启动时初始化一次,并且在整个程序执行过程中保持其值。
- 线程存储期限: 这种类型的对象在多线程环境中为每个线程提供独立的存储空间。它们的生命周期也与线程的存在相关联。
- 分配存储期限: 通过内存分配函数如
malloc或calloc分配的对象。它们的生命周期从分配函数返回开始,到使用free函数释放为止。
访问生命周期外的对象
- 未定义行为: 如果试图访问一个已经超出其生命周期的对象,那么结果是未定义的。这可能导致程序崩溃或其他不可预测的行为。
临时生命周期
- 结构体和联合体: 当结构体或联合体对象包含数组成员,并且这些对象是通过非左值表达式指定时,它们具有临时生命周期。
- 开始和结束: 临时生命周期从评估表达式时开始,根据C11标准,在整个表达式评估完成时结束。
例如,考虑下面的代码片段:
1struct Point {
2 int x, y;
3} point = {10, 20};
4
5// 使用非左值表达式
6(int[point.x])[0] = 42; // 此处point具有临时生命周期
在这个例子中,point作为数组下标的一部分出现在表达式中,因此它具有临时生命周期。需要注意的是,这种用法可能会导致复杂性和潜在的错误,因为一旦表达式计算完成,对point的引用就不再有效。
(六)命名空间
Lookup and name spaces - cppreference.com
名字空间的定义
当C程序解析标识符时,它需要确定该标识符所代表的内容。为了做到这一点,C语言为不同的标识符类别定义了不同的命名空间。每个命名空间都是独立的,这意味着可以在不同的命名空间中使用相同的标识符名称而不会产生冲突。

(七)类型
Type - cppreference.com
对象、函数和表达式具有一种称为类型的属性,该属性决定了存储在对象中或由表达式计算的二进制值的解释。
类型分类

兼容类型
在C语言中,兼容类型的概念很重要,因为它决定了不同翻译单元(Translation Units, TU)之间如何引用同一对象或函数。在 C 程序中,在不同的翻译单元中指向相同对象或函数的声明不必使用相同的类型。它们只需要使用足够相似的类型,称为兼容类型。如果两个声明引用同一个对象或函数但类型不兼容,则程序的行为是未定义的。

类型名称
类型名称在C语言中可以用于以下情况:
- 类型转换 (
cast) - 类型大小查询 (
sizeof)
类型名称还可以用来引入新的类型,例如通过typedef或者在类型转换表达式中。
(八)对象
Objects and alignment - cppreference.com
C语言中的对象是指程序执行环境中的一段数据存储区域,这段区域的内容可以表示一定的值。

整数类型的字节使用
- 当整数类型占据多个字节时,这些字节的使用方式由实现定义。
- 主要有两种实现:大端和小端。
- 大端实现将最高有效字节存储在最低地址处。
- 小端实现将最低有效字节存储在最低地址处。
二、执行单元
(九)主函数
main_function - cppreference.com
C语言中的main函数是程序的入口点,它是程序启动后第一个被调用的函数。
main函数的形式
main函数可以有不同的形式,常见的形式如下:
-
无参数形式:
1int main(void) { 2 // body 3}这种形式的
main函数没有参数,适用于不需要命令行参数的简单程序。 -
带参数形式:
1int main(int argc, char *argv[]) { 2 // body 3}这种形式的
main函数接收两个参数:argc和argv。argc是一个整数,表示命令行参数的数量(包括程序名称)。argv是一个指向字符串数组的指针,这些字符串是命令行参数。 -
其它扩展实现形式:
1int main(int argc, char *argv[], char *envp[]) { 2 // body 3}这种形式的
main函数接收三个参数:argc、argv和envp。除了argc和argv外,envp是一个指向环境变量字符串数组的指针。
参数说明
-
argc:- 表示传入程序的命令行参数的数量(包括程序名称)。
- 是一个非负整数。
-
argv:- 是一个指向字符串数组的指针,其中每个字符串都是一个命令行参数。
argv[0]通常指向程序名称。- 如果
argv[0]非空指针(即argc > 0),它指向一个表示程序名称的字符串;如果程序名称无法获取,则argv[0][0]保证为零。 argv[argc]是空指针。
返回值
main函数的返回值具有特殊的意义:
- 如果
main函数的返回类型与int兼容,那么从main函数的初始调用返回相当于调用了exit函数,并将main函数返回的值作为参数传递给exit函数。 - 返回值为0或
EXIT_SUCCESS表示成功终止。 - 返回值为
EXIT_FAILURE表示失败终止。
特殊性质
-
原型不可提供:
main函数的原型不能由程序提供。
-
退出行为:
- 如果
main函数的返回类型与int兼容,那么从main函数返回的行为等同于调用exit函数,并传递main函数返回的值作为参数。这会触发一系列标准清理操作,比如调用atexit注册的函数、关闭和刷新所有输出流、删除通过tmpfile创建的文件,并将控制权返回给执行环境。
- 如果
-
未定义的行为:
- 如果
main函数执行了一个未指定返回值的return语句,或者到达了函数结尾而没有执行return,则返回给执行环境的终止状态是未定义的(直到C99标准)。 - 如果
main函数的返回类型与int不兼容(例如void main(void)),返回给执行环境的值是未指定的。如果main函数的返回类型与int兼容,但是控制流到达了函数结尾而没有执行return,则行为等同于执行return 0;(自C99标准起)。
- 如果
(十)语句
Statements - cppreference.com
(十一)表达式
Expressions - cppreference.com
(十一)初始化、声明与定义

(十二)函数

致读者:
本文略显潦草地总结了C的一些知识点,难免有疏漏之处,本人知识有限也无法提供足够专业的知识分析,仅仅是作为一个参考,概览一些C的语法面貌。本文的目的,是作为一个小总结和再回顾。虽然是总结,但是可以发现的是,对于C的整体语法体系,这里仅仅是探明了一部分,至少本人没有去完全了解C的语法体系。即使是作为技术的纯粹者和热爱者,完全熟练一门语言也需要时间,更何况C的灵活性和变化的应用环境。所以倘若有读者能在这里得到点什么,这篇文章也算有点意义了。对于较为庞大的思维导图,本文提供了相应文件,读者可以自行修改。
相关文章:
C语言笔记(第n版):知识清单
注:本文参考自【C reference - cppreference.com】和【C 语言参考 | Microsoft Learn】,颇有点借花献佛的意味…… C 程序是一系列包含声明的文本文件(通常为头文件和源文件)的序列。它们经过转换成为可执行程序,当操作…...
【香橙派系列教程】(四)基于ARM-Linux架构的语音控制刷抖音项目
【四】基于ARM-Linux架构的语音控制刷抖音项目 文章目录 【四】基于ARM-Linux架构的语音控制刷抖音项目1.语音模块配置1.创建产品2.引脚配置3.词条定义4.添加控制5.发布版本6.烧录固件 2.编程实现语音和开发板通信3.手机接入Linux热拔插1.dmesg命令2.adb调试踩坑问题 3.总结 4.…...
Java----反射
什么是反射? 反射就是允许对成员变量、成员方法和构造方法的信息进行编程访问。换句话来讲,就是通过反射,我们可以在不需要创建其对象的情况下就可以获取其定义的各种属性值以及方法。常见的应用就是IDEA中的提示功能,当我…...
相似度计算方法
一、相似度计算方法 相似度算法是计算两个或多个对象之间相似程度的方法,这些对象可以是文本、图像、音频等不同类型的数据。在计算机科学、信息检索、推荐系统、数据挖掘等领域中,相似度算法具有广泛的应用。 二、应用场景 搜索引擎:用于文…...
Vue 点击markdown页内链接,路由设置不跳转
在路由index.js里添加路由守卫: router.beforeEach((to,from,next)>{//如果是md页内链接“#xxx”,则不跳转const hash window.location.hash;if(hash.startsWith(#)) {next(false);}else{...其他控制代码next();} });当markdown用[标题链接](#标题名…...
IOday4
一、思维导图 二、练习 1、使用父子进程完成两个文件的拷贝,父进程拷贝前一半内容,子进程拷贝后一半内容,子进程结束后退出,父进程回收子进程的资源 #include<myhead.h> int main(int argc, const char *argv[]) {//判断终…...
智能座舱背后主流车机平台(SA8155/SA8295)的高通Hexagon DSP是什么?
智能座舱背后主流车机平台(SA8155/SA8295)的高通Hexagon DSP是什么? 一、高通Hexagon DSP的辉煌发展历程 高通,作为全球领先的无线通信技术创新者,其处理器技术一直走在行业前列。随着智能手机和物联网设备的普及,对处理器性能的…...
linux进程控制——进程等待——wait、waitpid
前言:本节内容仍然是进程的控制,上一节博主讲解的是进程控制里面的进程创建、进程退出、终止。本节内容将讲到进程的等待——等待是为了能够将子进程的资源回收,是父进程等待子进程。 我们前面的章节也提到过等待, 那里的等待是进…...
Shell脚本的进程管理
进程管理是系统管理的重要方面,通过对进程的监控、启动、停止和重启,可以保证系统的稳定运行。Shell脚本是一种强大的工具,可以对进程进行自动化管理,提高效率和准确性。 参考:shell脚本进程管理 - CSDN文库 shell脚本…...
JLink烧录失败
1. 现象: 这个位置是灰色的,没有SW Device信息。 MDK下面的打印: J-Flash的打印: windows上面的弹框的现象没有截屏。 2. 解决办法: 1.打开J-Link Commander,输入unlock kinetis,看现象不起作用,网…...
Monorepo简介
Monorepo 第一章:与Monorepo的邂逅第二章:Multirepo的困境第三章:Monorepo的魔力 - 不可思议的解决问题能力第四章:Monorepo的挑战与应对策略第五章:总结第六章:参考 第一章:与Monorepo的邂逅 …...
SpringBoot打包为jar包,打包前注意事项及打包教程
在打包 Spring Boot 项目为 JAR 包之前,有一些重要的注意事项和步骤,以确保打包过程顺利并生成一个可正常运行的 JAR 包: 1. 检查依赖和版本 确保所有依赖项和插件版本是最新且兼容的,特别是 Spring Boot 版本和其相关依赖的版本…...
B端系统UI个性化设计:感受定制之美
B端系统UI个性化设计:感受定制之美 引言 艾斯视觉作为ui设计和前端开发从业者,其观点始终认为:在当今竞争激烈的商业环境中,B端(Business-to-Business)系统的设计不再仅仅是功能性的堆砌,而是…...
前端常用 utils 工具封装
// 函数防抖 export function debounce(fn, interval) {let timerreturn function (this, ...args) {clearTimeout(timer)const context thislet params [...args]timer setTimeout(() > {fn.call(context, ...params)}, interval || 1000)} }// 函数节流 export functio…...
项目都做完了,领导要求国际化????--JAVA后端篇
springboot项目国际化相信各位小伙伴都会,很简单,但是怎么项目都做完了,领导却要求国际化文件就很头疼了 国际化的SpringBoot代码: 第一步:创建工具类 /*** 获取i18n资源文件** author bims*/ public class Message…...
国内备受好评PostgreSQL数据库性能如何?
为什么国内很多数据库采用PostgreSQL数据库作为基础,再次开发自己的产品呢?不仅仅是因为PostgreSQL数据库开源免费、PostgreSQL 数据库的性能也是相当出色的,具有以下几个方面的特点: 1. 处理大规模数据: - 能够有效地管理和处…...
彻底搞懂前端跨域解决方案
一、浏览器的同源策略 1、同源策略概述 同源策略是浏览器为确保资料安全,而遵循的一种策略,该策略对访问资源进行了一些限制。 2、什么是源(origin)? 3、示例 4、同源请求 5、非同源请求 二、跨域会受到哪些限制 1…...
Kafka基础概念
MQ消息中间件 1)总览: 消息中间件 这里我们主要学习的是kafka的基础概念 具体参考黑马头条:https://www.bilibili.com/video/BV1Qs4y1v7x4/?spm_id_from333.337.search-card.all.click 2)消息中间件对比 3)Kafka介…...
【论文阅读笔记】DeepCAD: A Deep Generative Network for Computer-Aided Design Models
1 引言 现有3D生成模型: 3D点云:大量离散的3D点组成的数据表示形式; 多边形网格:一系列相连的多边形组成的3D模型; 水平集场:使用数值函数来表示物体的边界,并根据函数值的正负来确定物体内部…...
《如鸢》开通官号,女性向游戏爆款预定
今天,备受瞩目的沉浸式剧情卡牌手游《如鸢》正式开通了官方社媒账号并发布了玩家信。 《如鸢》由灵犀互娱倾力打造,游戏不仅拥有跌宕起伏的权谋剧情,更采用Live2D技术,为玩家带来沉浸式的游戏体验,吸引了众多玩家关注。…...
利用最小二乘法找圆心和半径
#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个生活电费的缴纳和查询小程序
一、项目初始化与配置 1. 创建项目 ohpm init harmony/utility-payment-app 2. 配置权限 // module.json5 {"requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.GET_NETWORK_INFO"…...
uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
日常一水C
多态 言简意赅:就是一个对象面对同一事件时做出的不同反应 而之前的继承中说过,当子类和父类的函数名相同时,会隐藏父类的同名函数转而调用子类的同名函数,如果要调用父类的同名函数,那么就需要对父类进行引用&#…...
Vue 模板语句的数据来源
🧩 Vue 模板语句的数据来源:全方位解析 Vue 模板(<template> 部分)中的表达式、指令绑定(如 v-bind, v-on)和插值({{ }})都在一个特定的作用域内求值。这个作用域由当前 组件…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...


