
C语言
文章平均质量分 79
以实战为基础,记述所有有关C语言知识点。
猫猫的小茶馆
用心做开发。专注于嵌入式技术,熟悉linux驱动开发,Linux系统搭建与移植,fpga,dsp,arm开发,pcb工艺,汇集了工作多年遇到的问题,与一些总结,有些是linux内核的源码级别的讲解,同时整个博客构建成了嵌入式的知识体系,专注于服务从事嵌入式软件开发的朋友。
展开
-
【C语言】C语言中的隐式规则
如果在代码块内部声明了和外层同名的变量,内部的变量会隐藏外部的,这可能导致意料之外的行为。另外,链接属性,比如未加static的函数默认是extern的,可以被其他文件访问,这也是隐式的规则。类型转换方面,比如整数和浮点数之间的运算,会自动将整数转换为浮点数,这也是隐式的。总的来说,这篇文章尽可能的涵盖了C语言中常见的隐式规则,解释它们的原理,可能带来的问题,以及如何避免。另外,我们要提到现代C标准(如C99、C11)中的变化,比如隐式函数声明在C99中不再允许,但有些编译器仍支持,导致可移植性问题。原创 2025-02-11 16:53:06 · 604 阅读 · 0 评论 -
【C语言】头文件
所以学习过C语言的朋友都熟悉这样一段代码:那么,你真的了解 吗? 到底是什么呢? 和 这两种写法皆可行吗?为什么?这二者有何区别呢?如果让你自己写一个类似头文件 的头文件,你能写出来并在大型项目中四处引用属于自己的头文件吗?这篇文章像大家详细介绍 C语言中的 头文件: 头文件是一个包含函数声明、宏定义、数据类型定义和全局变量声明的文件,通常配合 .c 源文件使用。头文件通过 指令被引入到源文件中(或其他头文件中)。头文件通常包含以下内容:宏定义:可以在头文件中定义一些宏,用于常量表达原创 2024-12-18 16:16:49 · 4177 阅读 · 0 评论 -
【C语言】C语言的潜规则:运行环境对C程序执行特性的影响
C 语言中有许多未定义行为(如整数溢出、空指针解引用),不同编译器和平台可能会表现不同。原创 2024-12-06 19:05:56 · 1167 阅读 · 0 评论 -
【C语言】变参函数
返回值类型 函数名(固定参数, ...) {va_list 参数列表;// 定义一个 va_list 类型的变量,用于访问变参va_start(参数列表, 固定参数);// 初始化 va_list,指定最后一个固定参数// 使用 va_arg() 宏获取变参va_end(参数列表);// 清理 va_list。原创 2024-12-03 22:41:59 · 798 阅读 · 0 评论 -
【C语言】递归的内存占用过程
递归虽然简单优雅,但需要仔细处理内存占用和递归深度问题,特别是在资源受限的嵌入式系统中需要特别注意内存空间的使用情况。在C语言中,递归的实现会占用内存栈(Call Stack),每次递归调用都会在栈上分配一个新的。那么,在递归的过程中到底发生了什么事情呢?以下将通过文字解析和图示说明递归对内存的占用情况,让大家直观的看见递归的过程。递归调用时,每次调用都会创建一个新的栈帧,压入到内存栈中。递归结束时,函数逐层返回,栈帧依次弹出释放。运行上述程序会导致栈溢出,因为递归调用的栈帧无限增长,超过了栈的容量。原创 2024-12-03 21:34:43 · 1196 阅读 · 0 评论 -
【C语言】结构体、联合体、枚举类型的字节大小详解
结构体是一种将多个类型的变量组合在一起的复合数据类型,每个成员都有自己的存储空间。每个成员按顺序存储。目的:创建新的类型,可面向对象编程,实例化一整个对象 —> 结构体。struct [标签] {成员属性1;成员属性2;成员属性3;成员属性4;// 结构体的关键字 : struct// 标签 可有 可无// 一个个成员都是 分号 结尾int b;char c;// 有了新的类型//定义该类型变量:int b;char c;} xx;//取别名:int b;char c;原创 2024-11-28 20:41:35 · 1308 阅读 · 0 评论 -
【C语言】位域、无名位域和空域详解
C语言不太好学的原因之一就是有大量这类复杂的抽象概念,容易把人绕晕,所以必须结合图片、动画、实际开发中的场景和编译代码片来逐步讲解,在经过了这一轮的理解之后,重新再看这些概念,便会觉得它们很熟悉且通俗易懂,在实际编程中你也能通过开发经验来自行判断技术方案的优势和劣势分别是什么,从而使用适合你的实际开发场景的技术方案。在C语言中,是一种特殊的,允许程序员按位(bit)操作和存储数据,从而节省内存空间。位域可以指定字段的位宽,限制某个成员占用的位数。位域在嵌入式编程、通信协议解析等场景中非常常见。原创 2024-11-28 20:34:44 · 1374 阅读 · 0 评论 -
【C语言】结构体嵌套
/ 嵌套一个结构体Outer:外层结构体。Inner:内层结构体,作为外层结构体的一个成员。看起来很简单对不对,没错,在编程中,即便是看起来非常复杂的结构其底层也只是由最为简单的模块拼接而成的。结构体嵌套允许我们在一个结构体中通过组合的方式包含另一个结构体,这样,从而构建更复杂的数据结构。// 定义内部结构体int x;int y;// 定义外部结构体// 嵌套结构体int z;// 初始化嵌套的结构体成员// 打印嵌套结构体成员return 0;原创 2024-11-28 16:03:50 · 2507 阅读 · 0 评论 -
【C语言】宏定义详解
在C语言中,宏定义是一种预处理指令,使用#define关键字定义。它由预处理器(Preprocessor)在编译前处理,用于定义常量、代码片段或函数样式的代码替换。宏是一种强大的工具,可以提高代码的可读性、可维护性和效率,但也需要谨慎使用,以避免潜在的错误。宏定义属于C/C++语言预处理功能的范畴,要透彻的搞明白宏定义,就需要先理解预处理的概念。使用预处理功能可以改变程序设计环境,提高编译效率。原创 2024-11-27 00:10:30 · 1326 阅读 · 0 评论 -
【C语言】作用域和存储类(结合作用域讲解)
在说存储类之前,我们先要清晰C语言中的作用域有哪些,然后,结合作用域来看存储类便能够一目了然,因为存储类所在的存储空间、生命周期、作用域和链接属性等必须在理解了作用域的基础之上进行。这里用一篇文章结合二者一起讲解,而不是分开讲解,是因为存储类的使用在C语言中非常普遍,而存储类的使用必须结合作用域和适用场景。二者有着密不可分的联系。原创 2024-11-26 02:48:54 · 1021 阅读 · 0 评论 -
【操作系统】操作系统的分页机制和野指针之间的关系详解
分页是一种存储机制,它允许操作系统以页面的形式将进程从辅助存储器检索到主存储器中。在分页方法中,主内存被划分为小的固定大小的物理内存块,称为帧。帧的大小应与页的大小保持相同,以最大限度地利用主存并避免外部碎片。分页用于更快地访问数据,它是一个逻辑概念。原创 2024-11-23 16:01:53 · 815 阅读 · 0 评论 -
【C语言】volatile 防止编译的时候被优化
因为编译器在很多时候为了提升程序的运行效率,会跳过和优化掉一些没用的代码,或者直接从寄存器中或者缓存中读取某些变量的值,因为从寄存器或者缓存中取值速度要比内存快,如果这个变量是个共享数据,或者有可能被中断等程序修改,那么,我们读取到的数据就有可能跟内存中的数据不一致。就是通过循环延长CPU的时间,常见于流水灯、蜂鸣器这些对时间精度要求不高的地方,但是这样的代码却存在着很严重的缺陷,如果编译的过程中开启了优化,有些编译器会认为这几行代码是废话,什么事情也没干,在寄存器中会跳过这部分代码。原创 2024-11-19 18:55:04 · 758 阅读 · 0 评论 -
【C语言】指针常量和常量指针
在多线程编程中,指针常量可以用于确保多个线程访问同一个共享资源时,指针本身的地址不被改变。这种用法在需要访问固定数据结构或配置的场景中尤为重要。在这些用法帮助确保数据的安全性和代码的稳定性,特别是在复杂或多线程的应用程序中。定义:指针指向的内容是常量,不能通过该指针修改内容,但指针本身可以指向其他地址。定义:指针本身是常量,不能指向其他地址,但指针所指向的内容可以改变。两者都是指针,存储方式相同,但使用限制不同。指针常量和常量指针在内存中的存储方式主要区别在于。通过这两种指针的使用限制,可以。原创 2024-11-19 16:49:19 · 1172 阅读 · 1 评论 -
【C语言】字符数组
这些函数在字符串处理和内存管理中非常常用,但在使用时需注意缓冲区大小和越界问题。一维字符数组是存放一个字符串,二维字符数组像二维数值存储一样。使用cout直接输出字符串,需要字符数组的数组名,遇到。2、以字符串的方式初始化一维字符数组(推荐)<0:如果 str1 小于 str2。,编译器会自动在字符串的末尾 添加。0:如果 str1 大于 str2。1、逐个元素初始化(不推荐)描述的是字符串,比如字符串。字符作为字符串的结束标记。3、以上两种初始化的区别。循环遍历(逐个字符操作)原创 2024-11-19 15:01:43 · 548 阅读 · 0 评论 -
【C语言】值传递和地址传递
传地址,是传值的一种特殊方式,只是他传递的是地址,不是普通的如int,那么传地址以后,实参和行参都。既然 fun 是地址值,那么 fun 是什么类型?指针类型,因为它的本质是一个地址。传引用,真正的以地址的方式传递参数, 传递以后,行参和实参。原创 2024-11-14 23:10:02 · 663 阅读 · 0 评论 -
【C语言】指针数组和数组指针的区别
的情况就更好理解了,在这里“()”的优先级比 “[ ]” 高,“ * ”号和 p2 构成一个指针的定义,指针变量名为 p2,int 修饰的是数组的内容,即数组的每个元素。p1 先与 “[]” 结合,构成一个数组的定义,数组名为 p1,int *修饰的是数组的内容,即数组的每个元素。指针数组:首先它是一个数组,数组的元素都是指针,数组占多少个字节由数组本身的大小决定,每一个元素都是一个指针,在 32 位系统下任何类型的指针永远是占 4 个字节。指针数组可以说成是”指针的数组”,首先这个变量是一个数组。原创 2024-11-14 18:34:45 · 3533 阅读 · 0 评论 -
【C语言】指针的运算
指针 + n,则增加 n 倍指针的数据类型的大小,指针的增加并不是添加 3 个字节,而是三个数据类型大小的块。不同的数据类型增减的大小不同。但是我们不能对指针执行乘法、除法和位操作。指针的增量运算取决于指针的数据类型,它将会增加数据类型的大小的字节。原创 2024-11-13 20:26:13 · 184 阅读 · 0 评论 -
【C语言】指针的由来
其中,这里聊一下转化过程中的汇编语言,汇编语言由指令、寄存器和立即数组成,汇编语言中的立即数允许我们直接与内存互动,这是一种非常接近底层的操作方式,允许对硬件进行精确控制,包括寄存器和内存操作。因为在汇编语言中,我们是直接操作内存,在不同的硬件架构下,汇编语言的表现形式会有所不同,计算机的物理内存对应着相应的物理地址,这些事硬件直接使用的地址,操作系统并不会把物理内存直接暴露给我们,而是将其虚拟化,这就是我们称为的虚拟内存空间。在这一层次中,我们操作的是虚拟内存对应的虚拟地址,然后,在编译器的转化下,原创 2024-11-12 23:59:38 · 536 阅读 · 0 评论 -
【C语言】位运算
一个字节是8个比特,所以存储空间被优化了256倍,假如有1000w块开发板需要检测并返回结果,用对象的方式存储需要占用的内存空间是300GB的内存空间大小,如果我们换成用bit的方式实现检测,只需要占用2GB的存储空间大小便能够完成检测。那么1个bit位 :10010000 第一个和第四个合格,其他的不合格,由此,我们不需要使用object的方式进行存储,我们可能将原本占用了32个字节大小的存储空间的对象压缩成了一个比特,8个比特可以检测8个开发板的合格与否。提供对数据的精确控制,适合底层开发。原创 2024-11-09 02:49:04 · 721 阅读 · 0 评论 -
【C语言】浮点型数据存储 和 整型数据存储的区别
现在计算机中的浮点数存储都是遵循IEEE754/854标准,以二进制的科学计数法存放到内存中。“指数部分”,即次高有效的e个比特,存储指数部分;最后剩下的f个低有效位的比特,存储“有效数”(significand)的小数部分(在非规约形式下整数部分默认为0,其他情况下一律默认为1)。一定要很清楚数据在计算机的存储方式,知道数据布局可以帮助优化内存访问,提高程序运行效率;确保数据类型和大小正确,避免精度损失或数据截断;对于浮点数在计算机中有两种存储的精度,即单精度和双精度,单精度是32位,双精度是64位。原创 2024-11-09 02:33:08 · 434 阅读 · 0 评论 -
【C语言】字符型在计算机中的存储方式
ASCII(American Standard Code for Information Interchange,美国信息互换标准代码,ASCII)是基于拉丁字母的一套电脑编码系统。例如,字符串:“hello world” —>字符串多个字符组合在一起(C语言中没有string类型,以字符数组的形式存储字符串:“hello world” )ASCII对照表:https://www.jyshare.com/front-end/6318/查看系统中的ascii码:man ascii (显示如下/不完整)原创 2024-10-24 20:11:32 · 406 阅读 · 0 评论 -
【C语言】int类型整数取值范围的缘由
补码(+1):1|1000 0000 0000 0000 0000 0000 0000 0001(最高位溢出,所以不取)最小值原码为 0000 0000 0000 0000 0000 0000 0000 0001 = 1。+0的原码:0000 0000 0000 0000 0000 0000 0000 0000。-0的原码:1000 0000 0000 0000 0000 0000 0000 0000。反码:1000 0000 0000 0000 0000 0000 0000 0000。原创 2024-10-23 20:47:02 · 480 阅读 · 0 评论 -
【C语言】原码 反码 补码
在 a 中的存储就是 补码: 00000000 00000000 00001111 00110100。原码 : 人为分析: 00000000 00000000 00001111 00110100。反码 : 正数的反码 = 原码 00000000 00000000 00001111 00110100。补码 : 正数的补码 = 反码 00000000 00000000 00001111 00110100。补码 : 是机器的码,用来机器存储的。原码 : 是人分析的码,给人看的。原创 2024-10-19 23:59:45 · 462 阅读 · 0 评论 -
【C语言】C语言的编译过程
在计算机底层,CPU只能做一些小事情,例如从内存中获取指令,执行所需的任务,并将输出发送回内存,做数学运算,随着时代的发展,人工智能 (AI) 和图形密集型任务对CPU的要求也在逐步提高,但基本上也还是这几件事。在编译器中所产生的可执行程序为机器码,才是计算机最终所识别的内容。它是一连串二进制数组成的程序(如下图),被称为机器码。机器码是实际执行的程序。原创 2024-10-19 02:13:46 · 1260 阅读 · 0 评论 -
【C语言】占位符集合
字面意义,占位符就是先占住一个固定的位置,等着你再往里面添加内容的符号,广泛用于计算机中各类文档的编辑。格式占位符(%)是在C/C++语言中格式输入函数,如 scanf、printf 等函数中使用。其意义就是起到格式占位的意思,表示在该位置有输入或者输出。占位符是 C语言中非常有用的一种工具,可以通过指定不同的占位符来格式化输出不同类型的数据。原创 2024-10-17 02:34:30 · 748 阅读 · 0 评论