![](https://img-blog.csdnimg.cn/20190927151124774.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
C语言学习之路
文章平均质量分 83
学习书本上C语言
清风自在 流水潺潺
喜欢学习和分享,欢迎关注,一起进步!
展开
-
【C语言进阶剖析】45.C语言中的函数设计原则
文章目录一、函数设计原则二、总结一、函数设计原则函数从意义上应该是一个独立的功能模块 函数名要在一定程度上反映函数的功能 函数参数名要能够体现参数的意义 尽量避免在函数中使用全局变量 当函数参数不应该在函数体内部被修改时,应加上 const 声明 如果参数是指针,且仅作输入参数,则应加上 const 声明,如下:不能省略返回值的类型 如果函数没有返回值,那么应声明为 void 类型 对参数进行有效性检查 对于指针参数的检查尤为重要 不要返回指向“栈内存.原创 2022-04-15 08:00:00 · 611 阅读 · 0 评论 -
【C语言进阶剖析】44.C语言中的递归函数分析
文章目录一、递归的数学思想二、递归函数三、递归函数设计技巧四、递归函数设计示例一五、递归函数设计示例二六、递归函数设计示例三七、小结一、递归的数学思想递归是一种数学上分而自治的思想 递归需要有边界条件 当边界条件不满足时,递归继续进行 当边界条件满足时,递归停止 递归将大型复杂问题转化为与原问题相同但规模较小的问题进行处理。二、递归函数函数体内部可以调用自己 递归函数 函数体中存在自我调用的函数 递归函数是递归的数学思想在...原创 2022-04-15 07:30:00 · 250 阅读 · 0 评论 -
【C语言进阶剖析】43.C语言中的函数与宏分析
文章目录一、函数与宏二、宏的妙用三、小结一、函数与宏宏是由预处理器直接替换展开的,编译器不知道宏的存在 函数是由编译器直接编译的实体,调用行为由编译器决定 多次使用宏会导致最终可执行程序的体积增大 函数是跳转执行的,内存中只有一份函数体存在 宏的效率比函数要高,因为是直接展开,无调用开销 函数调用时会创建活动记录,效率不如宏 下面看一个函数与宏的示例,先看这个程序:#include <stdio.h>#define RESET(p, l...原创 2022-04-14 16:22:42 · 212 阅读 · 0 评论 -
【C语言进阶剖析】42.C语言中函数参数的秘密
文章目录一、函数参数二、程序的顺序点三、小结(上)四、调用约定五、可变参数六、可变参数的限制七、小结(下)一、函数参数函数参数在本质上与局部变量相同在栈上分配空间 函数参数的初始值是函数调用时的实参值 函数参数的求值顺序依赖于编译器的实现 下面看一个函数参数的求值顺序的示例:#include <stdio.h>int func(int i, int j){ printf("i = %d, j = %d\n", i...原创 2022-04-14 13:06:35 · 775 阅读 · 0 评论 -
【C语言进阶剖析】41.C语言中函数的意义
文章目录一、函数的由来二、模块化程序设计三、C 语言中的模块化四、面向过程的程序设计五、声名和定义六、小结一、函数的由来二、模块化程序设计三、C 语言中的模块化四、面向过程的程序设计面向过程是一种以过程为中心的编程思想 首先将复杂的问题分解为一个个容易解决的问题 分解过后的问题可以按照步骤一步步完成 函数是面向过程在 C 语言中的体现 解决问题的每个步骤可以用函数来实现五、声名和定义声明的意义在于告诉编译器程序单元的存在 定原创 2022-04-13 10:29:50 · 406 阅读 · 0 评论 -
【C语言进阶剖析】40.C语言中的内存操作经典问题分析
文章目录一、野指针二、野指针的由来三、基本原则四、小结(上)五、常见的内存错误六、内存操作的规则七、小结(下)一、野指针指针变量中的值是非法的内存地址,进而形成野指针 野指针不是 NULL 指针,是指向不可用内存地址的指针 NULL 指针并无危害,很好判断,也很好调试 C 语言中无法判断一个指针所保存的地址是否合法二、野指针的由来局部指针变量没有被初始化 指针所指向的变量在指针之前被销毁 使用已经释放过的指针 进行了错误的指针运算 进行了错误的强制原创 2022-04-12 15:03:47 · 194 阅读 · 0 评论 -
【C语言进阶剖析】39.C语言程序中的内存布局
文章目录一、程序文件的一般布局二、程序与进程三、程序文件的一般布局四、程序的内存布局五、程序术语的对应关系六、小结一、程序文件的一般布局不同代码在可执行程序中的对应关系二、程序与进程程序和进程不同 程序是静态的概念,表现形式为一个可执行文件 进程是动态的概念,程序由操作系统加载运行后得到进程 每个程序可以对应多个进程 每个进程只能对应一个程序 面试中的小问题 包含脚本代码的文本文件是一种类型的可执行程序吗?如果是,对应什么样的进程呢?原创 2022-04-11 22:55:40 · 199 阅读 · 0 评论 -
【C语言进阶剖析】38.C语言中的栈、堆和静态存储区
文章目录一、程序中的栈二、函数的调用过程三、函数调用的栈变化四、函数调用栈上的数据五、程序中的堆六、程序中的静态存储区七、小结一、程序中的栈栈是现代计算机程序里最为重要的概念之一 栈在程序中用于维护函数调用上下文 函数中的参数和局部变量存储在栈上栈保存了一个函数调用所需的维护信息 参数 返回地址 局部变量 调用上下文 二、函数的调用过程每次函数调用都对应着一个栈上的活动记录 调用函数的活动记录位于栈的中部 被调函数的活动记录.原创 2022-04-11 22:18:32 · 2670 阅读 · 5 评论 -
【C语言进阶剖析】37.C语言中的动态内存分配
文章目录一、动态内存分配的意义二、malloc 和 free三、关于 malloc(0)四、calloc 和 realloc五、小结一、动态内存分配的意义C语言中的一切操作都是基于内存的 变量和数组都是内存的别名 内存分配由编译器在编译期间决定 定义数组的时候必须指定数组长度 数组长度是在编译期就必须确定的 需求:程序运行的过程中,可能需要使用一些额外的内存空间二、malloc 和 freemalloc 和 free 用于执行动态内存分配和释放.原创 2022-04-08 14:48:31 · 916 阅读 · 0 评论 -
【C语言进阶剖析】36.C语言中的指针阅读技巧分析
文章目录一、右左法则二、小结一、右左法则从最里层的圆括号中未定义的标示符看起 首先往右看,再往左看 遇到圆括号或方括号时可以确定部分类型,并调转方向 重复2,3步骤,直到阅读结束 下面来看一组复杂指针,看看怎么阅读。#include <stdio.h>int main(){ int (*p1)(int*, int (*f)(int*)); int (*p2[5])(int*); int (*(*p...原创 2022-04-07 10:13:18 · 286 阅读 · 0 评论 -
【C语言进阶剖析】35.C语言中的函数与指针分析
文章目录一、函数类型二、函数指针三、回调函数四、小结一、函数类型C 语言中的函数有自己特定的类型 函数的类型由返回值,参数类型和参数个数共同决定,如 int add(int i, int j)的类型为 int(int, int) C 语言中通过 typedef 为函数类型重命名 typedef type name(parameter list) 如 typedef int f(int, int); typedef void ...原创 2022-04-04 17:39:40 · 135 阅读 · 0 评论 -
【C语言进阶剖析】34.C语言中的数组参数和指针参数分析
文章目录一、C语言中的数组参数退化为指针的意义二、二维数组参数三、等价关系四、被忽视的知识点五、小结一、C语言中的数组参数退化为指针的意义C 语言中只会以值拷贝的方式传递参数 当向函数传递数组时: 将整个数组拷贝一份传入函数 × 将数组名看做常量指针传数组首元素地址 √ C 语言以高效作为最初设计目标: a) 参数传递的时候如果拷贝整个数组执行效率将大大下降。 b) 参数位于栈上,太大的数组拷贝将导致栈溢出。 二、二维数组参数二...原创 2022-04-03 20:46:44 · 226 阅读 · 0 评论 -
【C语言进阶剖析】33.C语言中的多维数组和多维指针
文章目录一、指向指针的指针二、二维数组与二维指针三、数组名四、小结一、指向指针的指针指针的本质是变量 指针会占用一定的内存空间 可以定义指针的指针来保存指针变量的地址值 为什么需要指向指针的指针? 指针在本质上也是变量 对于指针也同样存在传值调用与传址调用 下面看一个重置动态空间大小(从 size 到 new_size)的代码:#include <stdio.h>#include <malloc.h>int re...原创 2022-04-02 22:24:28 · 827 阅读 · 0 评论 -
【C语言进阶剖析】32.C语言中的 main 函数与命令行参数
文章目录一、main 函数的概念二、main 函数的本质三、main 函数的参数四、main 函数一定是程序执行的第一个函数吗?五、小结一、main 函数的概念C语言中 main 函数称之为主函数 一个C程序是从 main 函数开始执行的二、main 函数的本质main 函数是操作系统调用的函数 操作系统总是将 main 函数作为应用程序的开始 操作系统将 main 函数的返回值作为程序的退出状态 下面看一下 main 函数的返回值: ...原创 2022-03-31 16:33:54 · 3241 阅读 · 2 评论 -
【C语言进阶剖析】31.C语言中的数组指针和指针数组分析
文章目录一、数组类型二、定义数据类型三、数组指针四、指针数组五、小结一、数组类型C语言中的数组有自己特定的类型 数组的类型由元素类型和数组大小共同决定例:int array[5] 的类型为 int[5]二、定义数据类型C语言中通过 typedef 为数组类型重命名:typedef type(name)[size];数组类型:typedef int(AINT5)[5]; typedef float(AFLOAT10)[10];数组定义:AINT5 iA原创 2022-03-30 10:47:16 · 194 阅读 · 0 评论 -
【C语言进阶剖析】30.C语言中的字符串典型问题分析
一、典型问题一下面的程序输出什么?为什么?分析snprintf 函数本身是可变参数函数,原型如下:int snprintf( char* buffer, int buf_size, const char*fomart,... )当函数只有 3 个参数时,如果第三个参数没有包含格式化信息,函数调用没有问题:相反,如果第三个参数包含了格式化信息,但缺少后续对应参数,则程序行为不确定。 下面编程看看究竟会输出什么:#include <...原创 2022-03-29 15:37:10 · 887 阅读 · 0 评论 -
【C语言进阶剖析】28.C语言中指针和数组分析
文章目录一、指针和数组分析(上)1.数组的本质2.指针的运算3.指针的比较4.小结二、指针与数组分析(下)1.数组的访问方式2.下标形式 VS 指针形式3.a 和 &a 的区别4.数组参数5.小结一、指针和数组分析(上)1.数组的本质数组是一段连续的内存空间 数组的空间大小为 sizeof(array_type) * array_size 数组名可看做指向数组第一个元素的常量指针2.指针的运算指针是一种特殊的变量,与整数的运算规则原创 2022-03-25 14:36:57 · 1548 阅读 · 0 评论 -
【C语言进阶剖析】29.C语言中的字符串
文章目录一、字符串的概念二、字符数组与字符串三、字符串字面量的秘密四、字符串的长度五、小结一、字符串的概念字符串是有序字符的集合 字符串是程序中的基本元素之一 C 语言中没有字符串的概念 C 语言中通过特殊的字符数组模拟字符串 C 语言中的字符串是以 ‘\0’ 结尾的字符数组 二、字符数组与字符串在C语言中,双引号引用的单个或多个字符是—种特殊的字面量 存储于程序的全局只读存诸区 本质为字符数组,编译器自动在结尾加上 ‘\0' 字符 三、字符串字原创 2022-03-25 15:07:59 · 1436 阅读 · 0 评论 -
【C语言进阶剖析】27.C语言中数组的本质分析
文章目录一、数组的概念二、数组的大小三、数组地址与数组名四、数组名的盲点五、小结一、数组的概念数组是相同类型的变量的有序集合二、数组的大小数组在一片连续的内存空间中存储元素 数组元素的个数可以显示或隐式指定 下面看一段数组初始化的代码:#include <stdio.h>int main(){ int a[5] = {1, 2}; int b[] = {1, 2}; printf("a[2...原创 2022-03-18 15:22:03 · 173 阅读 · 0 评论 -
【C语言进阶剖析】26.C语言中指针的本质分析
文章目录一、* 的意义二、传值调用与传址调用三、常量与指针四、小结一、* 的意义在指针声明时,* 号表示所声明的变量为指针 在指针使用时,* 号表示取指针所指向的内存空间中的值 如下:int i = 0;int j = 0;int* p = &i; //指针声明j = *p; //取值变量 p 保存着变量 i 的内存地址,即:p <--> &i *p <--> i* ...原创 2022-03-18 14:45:24 · 272 阅读 · 0 评论 -
【C语言进阶剖析】25.C语言中的 # 和 ## 操作符使用分析
文章目录一、# 运算符二、## 运算符三、小结 一、# 运算符# 运算符用于在预处理期将宏参数转换为字符串 # 的转换作用是在预处理期完成的,因此只在宏定义中有效 编译器不知道 # 的转换作用 用法:#define STRING(x) #xprintf("%s\n",STRING(Hello World!)); 下面通过一个示例感受一下: test.c:#include <stdio.h>#d...原创 2022-03-17 14:56:03 · 10965 阅读 · 0 评论 -
【C语言进阶剖析】24.C语言中的 #pragma 使用分析
一、#pragma 简介#pragma 用于指示编译器完成一些特定的动作 #pragma 所定义的很多指示字是编译器特有的 #pragma 在不同的编译器间是不可移植的 预处理器将忽略它不认识的 #pragma 指令 不同的编译器可能以不同的方式解释同一条 #pragma 指令 一般用法:#pragma parameter 注:不同的 parameter 参数语法和意义各不相同二、#pragma messagemessage 参数在大多数的编译器中...原创 2022-03-17 14:20:02 · 2536 阅读 · 3 评论 -
【C语言进阶剖析】23.C语言中的 #error 和 #line 使用分析
文章目录一、#error 的用法二、#line 的用法三、小结一、#error 的用法#error 用于生成一个编译错误消息 用法 #error message,message不需要用双引号包围 #error 编译指示字用于自定义程序员特有的编译错误消息,类似的,#warning 用于生成编译警告。#error 是一种预编译器指示字 #error 可用于提示编译条件是否满足 用法示例如下:编译过程中的任意错误信息...原创 2022-03-16 11:25:34 · 2734 阅读 · 0 评论 -
【C语言进阶剖析】22.C语言中的条件编译使用分析
一、基本概念条件编译的行为类似于 C 语言中的 if...else... 编译是预编译指示命令,用于控制是否编译某段代码二、条件编译的本质预编译器根据条件编译指令有选择的删除代码 编译器不知道代码分支的存在 if...else... 语句在运行期进行分支判断 条件编译指令在预编译期进行分支判断 可以通过命令行定义宏 gcc -Dmacro=value file.c gcc -Dmacro file.c 三、#include 的本质#include 的本质是将已经存在的文件内原创 2022-03-14 21:06:34 · 1216 阅读 · 0 评论 -
【C语言进阶剖析】21.C语言中的宏定义与使用分析
文章目录一、C语言中的宏定义二、宏定义表达式三、宏表达式与函数的对比四、有趣的问题五、强大的内置宏六、小结一、C语言中的宏定义#define是预处理器处理的单元实体之一 #define 定义的宏可以出现在程序的任意位置 #define 定义之后的代码都可以使用这个宏 #define 定义的宏常量可以直接使用 #define 定义的宏常量本质为字面量 下面的宏常量定义正确吗? 编写代码来测试:#define ERRO...原创 2022-03-13 15:16:55 · 1839 阅读 · 0 评论 -
【C语言进阶剖析】20.C语言中的链接过程
文件目录一、链接器的意义二、模块链接三、小结一、链接器的意义连接器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。二、模块链接静态链接 由链接器在链接时将库的内容直接加入到可执行程序中 Linux下静态库的创建和使用 编译静态库源码:gcc -c lib.c -o lib.o 生成静态库文件:ar -q lib.a lib.o 使用静态库编译:gcc main.c lib.a -o main.out ...原创 2022-03-11 15:00:24 · 2725 阅读 · 0 评论 -
【C语言进阶剖析】19.C语言中的编译过程
文章目录一、初识编译器二、程序被编译的过程三、小结一、初识编译器编译器是一个广义的概念,真正的编译器由下面几个模块组成,真正的编译器是进行语法分析和语义分析的。二、程序被编译的过程 如下,file.i 是中间代码,file.s 是一个汇编文件,file.o 是二进制文件。预编译 处理所有的注释,以空格代替 将所有的 #define 删除,并且展开所有的宏定义 处理条件编译指令 #if, #ifdef, #e...原创 2022-03-11 10:56:11 · 144 阅读 · 0 评论 -
【C语言进阶剖析】18.C语言中的三目运算符和逗号表达式
一、三目运算符三目运算符( a ? b : c)可以作为逻辑运算的载体 规则:当 a 的值为真时,返回 b 的值;否则返回 c 的值三目运算符( a ? b : c)的返回类型 通过隐式类型转换规则返回 b 和 c 中的较高类型 当 b 和 c 不能隐式转换到同一类型时将编译出错 二、逗号表达式逗号表达式是C语言中的“粘贴剂” 逗号表达式用于将多个子表达式连接为一个表达式 逗号表达式的值为最后一个子表达式的值 逗号表达式中的前 N-1 个子表达式可以没有返回值 逗号表达式原创 2022-03-10 22:16:17 · 1444 阅读 · 1 评论 -
【C语言进阶剖析】17.C语言中的 ++ 和 -- 操作符分析
一、++,-- 操作符的本质++ 和 -- 操作符对应两条汇编指令 前置 变量自增(减)1 取变量值 后置 取变量值 变量自增(减)1 二、++,-- 操作符使用分析C 语言中只规定了 ++ 和 -- 对应指令的相对执行次序 ++ 和 -- 对应的汇编指令不一定连续运行 在混合运算中,++ 和 -- 的汇编指令可能被打断执行++ 和 -- 参与混合运算结果是不确定的。笔试面试中的“奇葩”题贪心法:++,-- 表达式的阅读技......原创 2022-03-10 21:41:16 · 5212 阅读 · 0 评论 -
【C语言进阶剖析】16.C语言中的位运算符分析
文章目录一、位运算符分析二、小贴士三、位运算与逻辑运算四、小结一、位运算符分析C语言中的位运算符位运算符直接对 bit 位进行操作,其效率最高。& 按位与 | 按位或 ^ 按位异或 ~ 取反 << 左移 >> 右移 左移和右移注意点 左操作数必须为整数类型 char 和 short 被隐式转换为 int 后进行移位操作 右操作数的范围必须为:[0,3...原创 2022-03-09 10:59:32 · 512 阅读 · 0 评论 -
【C语言进阶剖析】15.C语言中的逻辑运算符分析
文章目录一、&& 与 II 分析二、!分析三、小结一、&& 与 II 分析下面的程序运行结束后,i, j,k 的值分别为多少?#include <stdio.h>int main(){ int i = 0; int j = 0; int k = 0; ++i || ++j && ++k; printf("i = %d\n", i); pr...原创 2022-03-07 20:44:13 · 853 阅读 · 0 评论 -
【C语言进阶剖析】14.C语言中的单引号和双引号
一、单引号和双引号C语言中的单引号用来表示字符字面量 C语言中的双引号用来表示字符串字面量'a'表示字符字面量,在内存中占1个字节,'a'+1表示'a'的ASCII码加1,结果为'b'"a"表示字符串字面量,在内存中占2个字节,"a"+1表示指针运算,结果指向"a"结束符'\0'...原创 2022-03-07 19:58:03 · 15496 阅读 · 1 评论 -
【C语言进阶剖析】13.C语言中的接续符和转义符
文章目录一、接续符的意义二、接续符的使用三、转义符的意义四、转义符的使用五、转义符和其他的语法混合六、小结一、接续符的意义C语言中的接续符(\)是指示编译器行为的利器下面看一段接续符的代码(代码1-1):#in\clud\e <st\dio.h>in\t m\ain(\){pri\ntf\ (\ "Hello AutumnZe.\n" )\ ; ret\urn 0;}可以看到上原创 2022-03-07 16:41:24 · 1412 阅读 · 0 评论 -
【C语言进阶剖析】12.C语言中的注释符号
一、注释规则编译器在编译过程中使用空格替换整个注释 字符串字面量中的 // 和 /*...*/ 不代表注释符号 /*......*/ 型注释不能被嵌套 下面看一下这样一段代码:原创 2022-03-07 14:20:16 · 2160 阅读 · 0 评论 -
【C语言进阶剖析】11.C语言中的 enum, sizeof, typedef 分析
文章目录一、枚举类型的使用方法二、sizeof 关键字的用法三、typedef 的意义四、小结一、枚举类型的使用方法enum 是 C 语言中的一种自定义类型 enum 值是可以根据需要自定义的整型值 第一个定义的 enum 值默认为 0 默认情况下的 enum 值是在前一个定义值的基础上加 1 enum 类型的变量只能取定义时的离散值 enum 中定义的值是C语言中真正意义上的常量 在工程中 enum 多用于定义整型常量 下面看一段 enum 的使用代...原创 2022-03-03 17:13:39 · 698 阅读 · 0 评论 -
【C语言进阶剖析】10.C语言中的 struct 和 union 分析
文章目录一、struct 的小秘密二、结构体与柔性数组三、C语言中的 union四、小结一、struct 的小秘密C语言中的 struct 可以看作变量的集合struct 的问题:空结构体占用多大内存?下面编写程序看一下吧:#include <stdio.h>struct TS{};int main(){ struct TS t1; struct TS t2; printf("sizeof(struct T..原创 2022-03-03 15:51:34 · 735 阅读 · 0 评论 -
【C语言进阶剖析】9.C语言中的 const 和 volatile 分析
文章目录一、const 只读变量二、const 全局变量的分歧三、const 的本质四、const 修饰函数参数和返回值五、volatile 解析六、小结一、const 只读变量const 修饰的变量是只读的,本质还是变量 const 修饰的局部变量在栈上分配空间 const 修饰的全局变量在全局数据区分配空间 const 只在编译期有用,在运行期无用const 修饰的变量不是真的常量,它只是告诉编译器该变量不能出现在赋值符号的左边。二、cons...原创 2022-03-02 22:40:40 · 972 阅读 · 0 评论 -
【C语言进阶剖析】8.C语言中的 goto 和 void 分析
文章目录一、关于 goto二、void 的意义三、小结一、关于 goto高手潜规则:禁用 goto 项目经验:程序质量与 goto 的出现次数成反比 最后的判决:将 goto 打入冷宫下面看一段 goto 副作用分析的代码:#include <stdio.h>#include <malloc.h>void func(int n){ int* p = NULL; if( n < 0 ) { .原创 2022-03-02 21:40:12 · 337 阅读 · 0 评论 -
【C语言进阶剖析】7.C语言中的循环语句
文章目录一、循环语句分析二、do ... while 语句的循环方式三、while 语句的循环方式四、for 语句的循环方式五、break和 continue 的区别六、do 和 break 的妙用七、小结一、循环语句分析循环语句的基本工作方式 通过条件表达式判定是否执行循环体 条件表达式遵循 if 语句表达式的原则 do,while,for的区别 do 语句先执行后判断,循环体至少执行一次 while 语句先判断后执行,循环体可能不执行 fo原创 2022-02-26 21:15:38 · 174 阅读 · 0 评论 -
【C语言进阶剖析】6.C语言中的分支语句
文章目录一、if 语句分析二、switch 语句分析三、小结一、if 语句分析if 语句用于根据条件选择执行语句 else 不能独立存在且总是与它最近的 if 相匹配 else 语句后可以接连其他 if 语句if 语句中零值比较的注意点 bool 型变量应该直接出现于条件中,不要进行比较 变量和 0 值比较时,0 值应该出现在比较符号左边(这条规则可以拓展为任意字面量与变量比较时,字面量应该放在左边,变量放在右边,这样即使手误写成了 = ,编译器也能发现).原创 2022-02-26 16:17:48 · 511 阅读 · 0 评论