
C语言进阶
C语言是基础语言,通过对底层语言的熟悉,了解基本编程规范,对之后学习C++,java,Python等语言都有很大帮助。通过对C语言的深度剖析,希望读者能够深入理解指针、结构体等高频知识点,关注基础语言,减少debug次数。
YLC_慕类
知行合一
展开
-
C语言笔记 第四十八课 函数设计原则
第四十八课 函数设计原则函数设计原则函数从意义上应该是一个独立的功能模块函数名要在一定程度上反映函数的功能函数参数名要能够体现参数的意义尽量避免在函数中使用全局变量 void sc(char *s1, char *s2); void str_copy(char *str_dest, char ...原创 2019-01-14 20:49:23 · 235 阅读 · 0 评论 -
C语言笔记 第四十七课 递归函数分析
第四十七课 递归函数分析递归的数学思想递归是一种数学上分而自治的思想递归需要有边界条件当边界条件不满足时,递归继续进行当边界条件满足时,递归停止递归将大型复杂问题转化为原问题相同但规模较小的问题进行处理。递归函数函数体内存可以调用自己递归函数函数体中存在自我调用的函数递归函数是递归的数学思想在程序设计中的应用递归函数必须有递归出口函数的无限递归将导致程序栈溢出而崩溃递归...原创 2019-01-14 20:45:27 · 371 阅读 · 0 评论 -
C语言笔记 第四十六课 函数与宏分析
第四十六课 函数与宏分析函数与宏宏or 函数?宏是由预处理器直接替换展开的,编译器不知道宏的存在函数是由编译器直接编译的实体,调用行为由编译器决定多次使用宏会导致最终可执行程序的体积增大函数是跳转执行的,内存中只有一份函数体存在宏的效率比函数要高,因为是直接展开,无调用开销函数调用时会创建活动记录,效率不如宏46-1 函数与宏宏的效率比函数稍高,但是其副作用巨大宏是文本替...原创 2019-01-14 20:42:49 · 177 阅读 · 0 评论 -
C语言笔记 第四十五课 函数参数的秘密(下)
第四十五课 函数参数的秘密(下)参数入栈顺序函数参数的计算次序是依赖编译器实现的,那么函数参数的入栈次序是如何确定的呢?strcpy(s, “D.T.Software”);调用约定当函数调用发生时参数会传递给被调用的函数而返回值会被返回给函数调用者调用约定描述参数如何传递到栈中以及堆的维护方式参数传递顺序调用栈清理调用约定是预定义的可理解为调用协议调用约定通常用于库调用和库...原创 2019-01-14 20:39:30 · 194 阅读 · 0 评论 -
C语言笔记 第四十四课 函数参数的秘密(上)
第四十四课 函数参数的秘密(上)函数参数函数参数在本质上与局部变量相同在栈上分配空间函数参数的初始值是函数调用时的实参值函数参数的求值顺序依赖于编译器的实现下面的程序输出什么?为什么?int k =1;printf(“%d,%d\n”, k++, k++);2,1 原因:由编译器决定44-1 函数参数的求值顺序#include <stdio.h>int fu...原创 2019-01-14 20:35:49 · 185 阅读 · 0 评论 -
C语言笔记 第四十三课 函数的意义
第四十三课 函数的意义C语言中的函数函数的由来程序 = 数据 + 算法C程序 = 数据 + 函数(C语言核心)函数的意义模块化程序设计C语言中的模块化面向过程的程序设计面向过程是一种以过程为中心的编程思想首先将复杂的问题分解为一个个容易解决的问题分解过后的问题可以按照步骤一步步完成函数是面向过程在C语言中的体现解决问题的每个步骤可以用函数来实现声明和定义声明的意义...原创 2019-01-14 20:33:11 · 251 阅读 · 0 评论 -
C语言笔记 第四十二课 内存操作经典问题分析二
第四十二课 内存操作经典问题分析二常见内存错误结构体成员指针未初始化结构体成员指针未分配足够的内存内存分配成功,但并未初始化内存操作越界42-1 常见内存错误#include <stdio.h>#include <malloc.h>void test(int* p, int size){ int i = 0; for(i=0; i<...原创 2019-01-14 20:30:59 · 169 阅读 · 0 评论 -
C语言笔记 第四十一课 内存操作经典问题分析一
第四十一课 内存操作经典问题分析一野指针指针变量中的值是非法的内存地址,进而形成野指针野指针不是NULL指针,是指向不可用内存地址的指针NULL指针并无危害,很好判断,也很好调试C语言中无法判断一个指针所保存的地址是否合法野指针的由来局部指针变量没有被初始化指针所指向的变量在指针之前被销毁使用已经释放过的指针进行了错误的指针运算进行了错误的强制类型转换40-1 野指针初探...原创 2019-01-14 20:24:28 · 167 阅读 · 0 评论 -
C语言笔记 第四十课 程序的内存布局
第四十课 程序的内存布局程序文件的一般布局不同代码在可执行程序中的对应关系程序与进程—操作系统原理程序和进程不同程序是静态的概念,表现形式为一个可执行文件进程是动态的概念,程序由操作系统加载运行后得到进程每个程序可以对应多个进程每个进程只能对应一个程序面试中的小问题:包含脚本代码的文本文件是一种类型的可执行程序吗?如果是,对应什么样的进程呢? 可以,不是直接的可执行程序,...原创 2019-01-03 17:29:43 · 305 阅读 · 0 评论 -
C语言笔记 第三十九课 程序中的三国天下
第三十九课 程序中的三国天下程序中的栈栈是现代计算机程序里最为重要的概念之一栈在程序中用于维护函数调用上下文函数中的参数和局部变量存储在栈上栈是一种行为,一种先进后出的行为栈保存了一个函数调用所需的维护信息函数调用过程每次函数调用都对应着一个栈上的活动记录调用函数的活动记录位于栈的中部被调函数的活动记录位于栈的顶部函数调用的栈变化一从main()开始运行,esp栈顶指...原创 2019-01-03 17:27:02 · 327 阅读 · 0 评论 -
C语言笔记 第三十八课 动态内存分配
第三十八课 动态内存分配动态内存分配的意义C语言中的一切操作都是基于内存的变量和数组都是内存的别名内存分配由编译器在编译期间决定定义数组的时候必须指定数组长度数组长度是在编译期就必须确实的需求:程序运行的过程中,可能需要使用一些额外的内存空间malloc和freemalloc和free用于执行动态内存分配和释放malloc所分配的是一块连续的内存malloc以字节为单位,并...原创 2018-12-28 20:56:54 · 271 阅读 · 0 评论 -
C语言笔记 第三十七课 指针阅读技巧分析
第三十七课 指针阅读技巧分析笔试中的问题:下面的标识符代表什么含义?指针阅读技巧解析右左法则从最里层的圆括号中未定义的标识符看起首先往右看,再往左看遇到圆括号或方括号时可以确定部分类型,并调转方向重复2,3步骤,直到阅读结束int (*p) (int); ==> p为指针,指向函数,指向的函数有一个int参数,返回值为intint (p1)(int, int (f)(in...原创 2018-12-28 20:53:57 · 222 阅读 · 0 评论 -
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 p(int...原创 2018-12-25 21:50:55 · 201 阅读 · 0 评论 -
C语言笔记 第三十五课 数组参数和指针参数分析
第三十五课 数组参数和指针参数分析思考:为什么C语言中的数组参数会退化为指针?退化的意义C语言中只会以值拷贝的方式传输参数当向函数传递数组时:(错误的,设计当初的思路)将整个数组拷贝一份传入函数将数组名看做常量指针传数组首元素地址c语言以高效作为最初设计目标:a)参数传递的时候如果拷贝整个数组执行效率将大大下降b)参数位于栈上,太大的数组拷贝将导致栈溢出二维数组参数二维数组参...原创 2018-12-25 21:49:28 · 237 阅读 · 0 评论 -
C语言笔记 第三十四课 多维数组和多维指针
第三十四课 多维数组和多维指针指向指针的指针指针的本质是变量指针会占用一定的内存空间可以定义指针的指针来保存指针变量的地址值问题:为什么需要指向指针的指针?指针在本质上也是变量对于指针也同样存在传值调用与传址调用34-1 重置动态空间的大小二维数组与二级指针二维数组在内存中以一维的方式排布二维数组中的第一维是一维数组二维数组中的第二维才是具体的值二维数组的数组名可看做常...原创 2018-12-24 17:16:27 · 260 阅读 · 0 评论 -
C语言笔记 第三十三课 main函数与命令行参数
第三十三课 main函数与命令行参数main函数的概念C语言中main函数称之为主函数一个C程序是从main函数开始执行的下面的main函数定义正确吗?四个都正确33-1 main函数的原型究竟是什么main函数的本质main函数是操作系统调用的函数操作系统总是将main函数作为应用程序的开始操作系统将main函数的返回值作为程序的退出状态思考:为什么C编译器支持那么多不同的...原创 2018-12-24 17:13:31 · 247 阅读 · 0 评论 -
#include 和 #include""的区别
#include< file >编译程序会先到标准函数库中找文件 #include”file” 编译程序会先从当前目录中找文件参考原文 转: 在C程序中包含文件有以下两种方法: (1)用符号“<”和“>”将要包含的文件的文件名括起来。这种方法指示预处理程序到预定义的缺省路径下寻找文件。预定义的缺省路径通常是在INCLUDE环境变量中指定的,请看下...转载 2018-12-24 10:22:30 · 219 阅读 · 0 评论 -
C语言笔记 第三十二课 数组指针和指针数组分析
第三十二课 数组指针和指针数组分析思考下面这些声明合法吗?int array[5]; //标准数组定义 合法int matrix[3][3]; //二维数组int* pa = array; //array数组名初始化指针pa 合法int* pm = matrix; //问题:array代表数组首元素的地址,那么matrix代表什么?array和&array的地址值相同,但是...原创 2018-12-22 21:09:39 · 268 阅读 · 0 评论 -
C语言笔记 第三十一课 字符串典型问题分析(都是面试题)---基础很重要
第三十一课 字符串典型问题分析(都是面试题)—基础很重要典型问题一下面的程序输出什么?为什么?char buf[10] = {0};char src[] = “hello %s”;snprintf(buf, sizeof(buf), src);printf(“buf = %s\n”, buf);有警告,能编译,有可执行结果输出:buf = hello ??分析:snprintf...原创 2018-12-22 21:06:15 · 280 阅读 · 0 评论 -
C语言笔记 第三十课 C语言中的字符串
第三十课 C语言中的字符串字符串的概念字符串是有序字符的集合字符串是程序在的基本元素之一C语言中没有字符串的概念C语言中通过特殊的字符数组模拟字符串C语言中的字符串是以’\0’结尾的字符数组字符数组与字符串在C语言中,双引号引用的单个或多个字符是一种特殊的字面量存储于程序的全局只读存储区本质为字符数组,编译器自动在结尾加上’\0’字符下面那些是字符串的定义?2.3.4是3...原创 2018-12-20 17:24:17 · 279 阅读 · 0 评论 -
C语言笔记 第二十九课 指针和数组分析(下)
第二十九课 指针和数组分析(下)问题:数组名可以当做常量指针使用,那么指针是否也可以当做数组名来使用呢?可以数组的访问方式以下标的形式访问数组中的元素以指针的形式访问数组中的元素下标形式VS指针形式指针以固定增量在数组中移动时,效率高于下标形式指针增量为1且硬件具有硬件增量模型时,效率更高下标形式与指针形式的转换注意:现代编译器的生成代码优化率已大大提高,在固定增量时,下...原创 2018-12-20 17:22:14 · 247 阅读 · 0 评论 -
C语言笔记 第二十八课 指针和数组分析(上)
第二十八课 指针和数组分析(上)数组的本质数组是一段连续的内存空间数组的空间大小为sizeof(array_type)*array_size数组名可看做指向数组第一个元素的常量指针问题:1.a+1的意义是什么?结果是什么?2.指针运算的意义是什么?结果又是什么?28-1 a+1的结果是什么指针的运算指针是一种特殊的变量,与整数的运算规则为结论:当指针P指向一个同类型的数组...原创 2018-12-19 21:33:07 · 193 阅读 · 0 评论 -
C语言笔记 第二十七课 数组的本质分析
第二十七课 数组的本质分析数组的概念数组是相同类型的变量的有序集合数组的大小数组在一片连续的内存空间中存储元素数组元素的个数可以显示或隐式指定问题:a[2],a[3],a[4]的值是多少?b包含了多少个元素?27-1 数组的初始化int a[5] = {0}; 编程小技巧:初始化数组中所有的元素为0数组地址与数组名数组名代表数组首元素的地址数组的地址需要用取地址符...原创 2018-12-19 21:30:55 · 272 阅读 · 0 评论 -
C语言笔记 第二十六课 指针的本质分析
第二十六课 指针的本质分析变量回顾程序中的变量只是一段存储空间的别名,那么是不是必须通过这个别名才能使用这段存储空间?下面的程序输出什么?为什么?*号的意义在指针声明时,*号表示所声明的变量为指针在指针使用时,*号表示取指针所指向的内存空间中的值小贴士26-1 指针的使用示例32位系统的Ubuntu,存储的指针变量都是四位字节64位系统也是四位字节吗?八位传值调用与传址...原创 2018-12-18 11:38:49 · 187 阅读 · 0 评论 -
C语言笔记 第二十五课 #和##操作符使用分析
第二十五课 #和##操作符使用分析#运算符#运算符用于在预处理期将宏参数转换为字符串#的转换作用是在预处理期完成的,因此只在宏定义中有效编译器不知道#的转换作用用法25-1 #运算符的基本用法25-2#运算符的妙用##运算符##运算符用于在预处理期粘连两个标识符##的连接作用是在预处理期完成的,因此只在宏定义中有效编译器不知道##的连接作用用法25-3 ##运算符的基...原创 2018-12-18 11:35:23 · 148 阅读 · 0 评论 -
C语言笔记 第二十四课 #pragma使用分析
第二十四课 #pragma使用分析#pragma简介#pragma用于指示编译器完成一些特定的动作#pragma所定义的很多指示字是编译器特有的#pragma在不同的编译器间是不可移植的预处理器将忽略它不认识的#pragma指令不同的编译器可能以不同的方式解释同一条#pragma指令一般用法:#pragma parameter注:不同的parameter参数语法和意义各不相同#p...原创 2018-12-17 22:19:04 · 290 阅读 · 0 评论 -
C语言笔记 第二十三课 #error和#line使用分析
第二十三课 #error和#line使用分析#error的用法#error用于生成一个编译错误消息用法 #error messagemessage不需要用双引号包围#error编译指示字用于自定义程序员特有的编译错误消息,类似的,#warning用于生成编译警告。#error是一种与编译器指示字#error可用于提示编译条件是否满足编译过程中的任意错误信息意味着无法生成最终的可...原创 2018-12-17 22:12:57 · 232 阅读 · 0 评论 -
C语言笔记 第二十二课 条件编译使用分析
第二十二课 条件编译使用分析基本概念条件编译的行为类似于C语言中的if…else…条件编译是预编译指示命令,用于控制是否编译某段代码22-1 条件编译初探条件编译的本质预编译根据条件编译指令有选择的删除代码编译器不知道代码分支的存在if…else…语句在运行期进行分支判断条件编译指令在预编译期进行分支判断可以通过命令行定义宏gcc -Dmacro=value file.c或...原创 2018-12-14 10:26:26 · 257 阅读 · 0 评论 -
C语言笔记 第二十一课 宏定义与使用分析
第二十一课 宏定义与使用分析C语言中的宏定义#define是预处理器处理的单元实体之一#define定义的宏可以出现在程序的任意位置#define定义之后的代码都可以使用这个宏定义宏常量#define定义的宏常量可以直接使用#define定义的宏常量本质为字面量(不占用内存空间)下面的宏常量定义正确吗?完全正确,但编译不过去,3,4句语法不符合C语言21-1 宏定义分析宏定义...原创 2018-12-14 09:44:20 · 208 阅读 · 0 评论 -
C语言笔记 第二十课 链接过程简介
第二十课 链接过程简介链接器的意义处理器的主要作用是把各个模块之间相互引用的部分处理好,使得各个模块之间能够正确的衔接。模块链接静态链接由链接器在链接时将库的内容直接加入到可执行程序中Linux下静态库的创建和使用编译静态库源码:gcc -c lib.c -o lib.o生成静态库文件:ar -q lib.a lib.o使用静态库编译:gcc main.c lib.a -o ...原创 2018-12-14 09:41:18 · 221 阅读 · 0 评论 -
C语言笔记 第十九课 编译过程简介
第十九课 编译过程简介被隐藏了的事实初识编译器你不知道的事….o是二进制代码文件编译器做了什么预编译处理所有的注释,以空格代替(文本处理)将所有的#define删除,并且展开所有的宏定义处理条件编译指令#if,#ifdef,#elif,#else,#endif处理#include,展开被包含的文件保留编译器需要使用的#pragma指令编译指令示例:gcc -E file...原创 2018-12-14 09:37:40 · 233 阅读 · 0 评论 -
C语言笔记 第十八课 三目运算符和逗号表达式
第十八课 三目运算符和逗号表达式三目运算符三目运算符(a?b:c)可以作为逻辑运算的载体规则:当a的值为真时,返回b的值;否则返回c的值下面的程序运行结束后,a,b,c的值分别为多少?int a = 1;int b = 2;int c = 0;c = a<b?a:b;(a<b?a:b) = 3;18-1 三目运算符初探三目运算符(a?b:c)的返回类型通过隐式类...原创 2018-12-12 11:40:09 · 253 阅读 · 0 评论 -
C语言笔记 第十七课 ++和-- 操作符分析
第十七课 ++和-- 操作符分析++,- -操作符的本质++和- -操作符对应两条汇编指令前置 变量自增(减)1取变量值后置 取变量值变量自增(减)1++,- -操作符使用分析int i = 0;(i++) + (i++) + (i++); 0+1+2=3 i => 3(++i) + (++i) + (++i); 4+5+6=15 i => 6 g...原创 2018-12-12 11:37:49 · 296 阅读 · 0 评论 -
C语言笔记 第十六课 位运算符分析
第十六课 位运算符分析C语言中的位运算符位运算符直接对bit位进行操作,其效率最高位运算符操作&按位与I按位或^按位异或~取反<<左移>>右移异或运算法则:相同为0,不同为1位运算符分析左移和右移注意点左操作数必须为整数类型char和short被隐式转换为int后进行移位操作右操作数...原创 2018-12-10 15:04:41 · 244 阅读 · 0 评论 -
C语言笔记 第十五课 逻辑运算符分析
第十五课 逻辑运算符分析逻辑运算符&&,||和!真的很简单吗?下面的程序运行结束后,i,j,k的值分别是多少?int i = 0;int i = 0;int i = 0;++i || ++j && ++结果:i = 1j = 0k = 015-1 初探逻辑运算符程序中的短路||从左向右开始计算:当遇到为真的条件时停止计算,整个表达式为真...原创 2018-12-10 14:55:42 · 352 阅读 · 0 评论 -
C语言笔记 第十四课 单引号和双引号
第十四课 单引号和双引号C语言中的单引号用来表示字符字面量C语言中的双引号用来表示字符串字面量下面的程序片段合法吗?三条语句都合法,1、2语句有警告char* p1 = 1; //数字1char* p2 = ‘1’; //字符1char* p3 = “1”; //字符串1小贴士:字符字面量被编译为对应的ASCII码字符串字面量被编译为对应的内存地址printf的第...原创 2018-12-10 14:52:47 · 316 阅读 · 0 评论 -
C语言笔记 第十三课 接续符和转义符
第十三课 接续符和转义符接续符的意义C语言最终的接续符(\)是指示编译器行为的利器是否是合法程序? 合法13-1 初探接续符接续符的使用编译器会将反斜杠剔除,跟在反斜杠后面的字符自动接续到前一行在接续单词时,反斜杠之后不能由空格,反斜杠的下一行之前也不能由空格接续符适合在定义宏代码块时使用13-2接续符的应用转义符的意义C语言中的转义符(\)主要用于表示无回显字符,也可用于...原创 2018-12-10 14:51:06 · 229 阅读 · 0 评论 -
C语言笔记 第十二课 注释符号
第十二课 注释符号注释是C语言最重要的工具,我们先看自己有没有能力驾驭它,再讨论有没有必要深究。注释规则编译器在编译过程中使用空格替换整个注释字符串字面量中的//和/**/不代表注释符号/…/型注释不能被嵌套12-1 注释规则有趣的问题你觉得 y=x/*p是什么意思?作者本意:把x除以*p的结果赋值给y。编译器:将/*作为一段注释的开始,把/后的内容都当成注释内容,知道/出现为...原创 2018-12-10 14:47:28 · 457 阅读 · 0 评论 -
C语言笔记 第十一课 enum,sizeof,typedef分析
第十一课 enum,sizeof,typedef分析枚举类型的使用方法enum是C语言中的一种自定义类型enum值是可以根据需要自定义的整型值第一个定义的enum值默认为0默认情况下的enum值是在前一个定义值的基础上加1enum类型的变量只能取定义时的离散值枚举类型的特殊意义enum中定义的值是C语言中真正意义上的常量在工程中enum多用于定义整型常量11-1enum的使...原创 2018-12-10 14:44:38 · 297 阅读 · 0 评论 -
C语言笔记 第十课 struct和union分析
第十课 struct和union分析C语言中的struct可以看做变量的集合struct的问题:空结构体占用多大内存?10-1 空结构体的大小C语言中的灰色地带,观点一是空结构体无意义不能存在于C语言里面(VC10.0 /BCC),观点二是空结构体为空集合,空集合为零(GCC),这两种说法都争取,因为实际工程开发不会定义空指针。结构体与柔性数组柔性数组即数组大小待定的数组C语言中...原创 2018-12-07 11:33:43 · 338 阅读 · 0 评论