![](https://img-blog.csdnimg.cn/20201014180756757.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
C语言学习总结
文章平均质量分 78
澜色海湾
这个作者很懒,什么都没留下…
展开
-
37.0、C语言——C语言预处理(5) - 文件包含
当我们第二次重复引入该头文件的时候,依旧是#ifndef 判断 -> 由于前面引入过一次该头文件,所以 __TEST_H__ 已经定义过了,那么下面至 #endif 的代码全部失效 -> 不参与编译,这样就不会重复拷贝相同的代码了;那其实这个问题在开发中是不可避免的,因为假设 程序猿A、程序猿B、程序猿C 分工合作写一个项目,那么在最后项目程序对接的时候,三个人的代码肯定会合到一起,那么很容易出现头文件重复引入的问题发生;这是一种比较新的写法,更为简单一下,也能够和上面第一种方法一样达到同样的效果;原创 2022-09-26 15:44:04 · 632 阅读 · 0 评论 -
36.0、C语言——C语言预处理(4) - 条件编译
许多 C 的编译器提供了一种能力,允许在命令行中定义符号;用于启动编译过程;例如:当我们根据同一个源文件要编译出不同的一个程序的不同版本的时候,这个特性就有点用处了;(嘉定某个程序中声明了一个某个长度的数组,如果机器内存有限,我们需要一个很小的数组,但是另外一个机器内存大写,我们需要一个数组能够大写);原创 2022-09-26 14:35:04 · 421 阅读 · 0 评论 -
35.0、C语言——C语言预处理(3) - 宏 与 函数
当宏参数在宏的定义中出现超过了一次的时候,如果参数带有副作用,那额你在使用这个宏的时候就可能出现危险,导致不可预测的后果;副作用就是表达式求值的时候出现的永久性效果,原创 2022-09-26 12:48:54 · 496 阅读 · 0 评论 -
34.0、C语言——C语言预处理(2) - 预编译指令
预处理指令:# 开头的都叫做预处理指令,比如说 ->#define 定义标识符#define name stuff 【我们在定义#define标识符的时候用的都是大写,这是我们的约定】#define STR "澜色海湾"return 0;}#define 后面可以是 标识符名 也可以是 一段代码,无论是什么,都会在预处理阶段将代码中的相应的 标识符 进行替换;问题:在 #define后面需要加 分号;吗?原创 2022-09-25 17:14:20 · 458 阅读 · 0 评论 -
34.0、C语言——C语言预处理(2) - 运行环境简单了解
3. 开始执行程序代码;这个时候程序将使用一个运行时 堆、栈( stack ),存储函数的局部变量和返回地址;程序同时也可以使用静态 ( static )内存;存储于静态内存中的变量在程序的整个执行过程一直保留他们的值;1. 程序必须载入内存中;在有操作系统的环境中:一般这个由操作系统完成;在独立的环境中【就是在没有操作系统的情况下】,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存来完成;4. 终止程序,正常终止 main 函数;也有可能是意外终止;2. 程序的执行开始;原创 2022-09-25 14:18:11 · 168 阅读 · 0 评论 -
33.0、C语言——C语言预处理(1) - 翻译环境详解
首先每个目标文件中会分为不同的段,每段会存放一些程序的数据、代码等;不过每个目标文件的段结构、格式是一样的【这种格式被称作 elf 文件格式,感兴趣的可以百度一下】,只是每段存放的东西不一样;经过链接阶段时,首先会把每个目标文件中相对应的段位置里的数据合并到一起,最终形成一个目标文件;在经过编译阶段后,会形成 符号表,符号表中存放了符号以及他们的地址;那么重复的符号会合并,合并之后如果他们的地址不同则取 有效地址 存入到合并后的符号表中;原创 2022-09-25 13:59:23 · 389 阅读 · 0 评论 -
32.0、C语言——文件操作 (3)
那这里需要注意的是,如果在 ftell ( fp ) 之前用了 fgetc ( fp ) ,那么 fgetc() 去读了一次之后文件指针会往后移动一位,那么这时候如果用 ftell(fp) 算出的结果就是 1 了;2. fseek()函数,传入 -> 第一个参数 pf ,第二个参数向后偏移 2 个字符,第三个参数文件指针的位置从 SEEK_CUR(也就是文件的起始位置)开始;我们将 TEST.txt 文本文件置为空后,打开该文件,然后读取,得到的返回值是 -1,所以 EOF 的值为 -1。原创 2022-09-24 20:55:03 · 1720 阅读 · 0 评论 -
31.0、C语言——文件操作 (2)
如果打开成功,则会创建一个 FILE 类型的结构体去管理维护这个打开的文件,然后返回一个指向这块存放文件信息 FILE 结构体内存的指针,如果打开失败则会返回一个 NULL 空指针;但是如果是 ( 写文件 ) 打开文件,发现文件不存在,则新建一个该文件。1. 在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 指针变量指向该文件,也相当于建立了指针和文件的关系;2. 除非是给文件追加内存,否则其他任何改写文件的方式都是新建一个同名文件,然后将原来的文件销毁掉。,在使用结束之后应该。原创 2022-09-23 15:15:34 · 631 阅读 · 0 评论 -
30.0、C语言——文件操作 (1)
1. 磁盘上的文件是文件;2. 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件;程序文件:包括源程序文件 ( 后缀为 .c ),目标文件 ( windows环境后缀为 .obl ),可执行程序 ( windows环境后缀为 .exe );数据文件:文件的内容不一定是程序,而是程序运行时读写的数据;比如程序运行需要从中读取数据的文件,或者输出内容的文件;原创 2022-09-23 11:44:54 · 244 阅读 · 0 评论 -
29.0、C语言——通讯录实例_实现代码
【代码】29.0、C语言——通讯录实例_实现代码。原创 2022-09-22 16:58:24 · 465 阅读 · 0 评论 -
28.0、C语言——柔性数组
int arr[];}int i;}当我们查看该结构体占用的内存时,发现在结构体中柔型数组不占用内存,结构体的大小仅仅是除去柔型数组外其他元素的大小;【形式一】这是因为柔型数组在定义时未被赋予任何的内存空间,那么我们可以动态的赋予 柔性数组 内存空间的大小 ,int i;int arr[];}S;return 0;}这里相当于是先申请了一块结构体 S 大小的空间,然后又申请了20个字节的空间给 arr 柔性数组;原创 2022-09-22 14:57:29 · 244 阅读 · 0 评论 -
27.0、C语言——动态内存分配 (2)
1. 运行代码程序会出现崩溃的现象;2. 程序存在内存泄漏的问题;【str 以值传递的形式给 p,p 是GetMemory 函数的形参,只能函数内部有效,等 Getmemory 函数返回之后,动态开辟的内存空间尚未释放且无法找到,所以会造成内存泄漏】原创 2022-09-21 12:34:51 · 225 阅读 · 0 评论 -
26.0、C语言——动态内存分配 (1)
我们可以发现当使用 free( p ) 释放交给 p 管理的内存后,指针 p 仍然记得该内存的地址,那么这是非常危险的,因为该指针指向的地址空间已经不属于我们的程序了,这样非常的不安全,所以释放内存后 应该将 p 置为空 -> p = NULL;当我们要修改的内存太大了,无法将原有的内存修改成功的时候,此时 realloc() 函数会返回一个 NULL 指针,那么如果此时我们直接将 NULL 赋值给管理原来空间的指针 p 就直接将原来地址覆盖掉了,这样一来原来的内存空间也找不到了;原创 2022-09-20 12:31:04 · 216 阅读 · 0 评论 -
25.0、C语言——自定义数据类型_枚举和共用体
联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以也叫联合体);比如 ->union Un {char c;int i;};return 0;}1. 输出结果可以发现都是一样的地址内存空间;2. 说明变量 c 和 变量 a 同时共用同一块内存空间;但是我们会发现由于联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少应该是联合体中最大成员变量的大小(因为联合至少得有能力保存最大的那个成员的空间);原创 2022-09-18 12:20:24 · 221 阅读 · 0 评论 -
24.0、 C语言——自定义数据类型_位段
1. 位段的成员必须是: int 、 undigned int 、或 signed int;2. 位段的成员后边有一个冒号和一个数字;3. 当然在我们查阅了大量的资料之后,可以发现不仅仅是int类型,只要是整型就行,比如short 、 char 等都可以;4. 但是建议大家在定义成员变量的时候,尽量都是一个类型的;跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台问题的存在;原创 2022-09-17 17:01:26 · 534 阅读 · 0 评论 -
23.0、C语言——结构体的剖析与使用
short age;}s2,s3,s4;short age;}Student;struct Student s1 = {"小澜","1355841253","男",18};return 0;}原创 2022-09-16 16:05:51 · 439 阅读 · 0 评论 -
22.0、C语言——内存函数的剖析和使用
1. 在上面的 memcopy( ) 函数说道 -> 如果拷贝的数据内存发生重叠则无法正常拷贝,那其实 memmove ( ) 函数就是来解决这个问题的;【比如:int arr[] = {1,2,3,4,5,6,7,8,9,10};1. 函数 memcpy() 从 source 的位置开始向后复制 num 个字节的数据到 destination 的内存位置;3. 和 strcmp() 函数比较的方式差不多,一 一 对比,直到对比到两个不同的元素,或者对比完 num 个字节;【num 是字节数】原创 2022-09-15 15:09:17 · 178 阅读 · 0 评论 -
21.0、C语言——字符函数的剖析与使用
/转换成 小写字母;//转换成 大写字母;原创 2022-09-13 15:06:13 · 139 阅读 · 0 评论 -
20.0、C语言——字符串函数的使用和剖析
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在 常量字符串 中,或者字符数组中,字符串常量 适用于那些不做修改的字符串函数strlen ( )1.字符串将 ' /0 ' 作为结束标志,strlen函数返回的是在字符串中 ' /0 ' 前面出现的字符个数 (不包含 ' /0 ');2.参数指向的字符串必须要以 ' /0 ' 结束;3.注意函数的返回值size_t【查看源码后可知该类型被 typedef 后的 unsigned int 类型】,是无符号的。原创 2022-09-12 15:26:28 · 331 阅读 · 0 评论 -
19.0、C语言——指针笔试面试题
首先我们要明白二维数组初始化中他用的是 ( ) ,那么这就是一个逗号表达式,实际上初始化的数据为 1 ,3 ,5 ,0 , 0 ,0;0x00100014 【p的大小已知是20字节,所以 p + 1就会跳过 20 字节,20转换为十六进制就是0x14】那么指针 p 存放的就是 1 的地址,p[ 0 ] = p+0 所以p[ 0 ] = 1。*(&arr) = *(整个数组的地址) = arr = 数组名 = 首元素地址;最后输出的结果是:f f f f f f f c,-4。输出的结果为 2 ,5。原创 2022-09-09 12:58:31 · 459 阅读 · 0 评论 -
18.0、C语言——自定义qsort()函数
/两个元素交换int i = 0;i < width;i++) {e1++;e2++;}}//冒泡排序int i = 0;//确定要比较多少趟i++) {//确定每趟要比较的对数j++) {//交换}}}}//int类型数组的比较方式,//这里由于void类型的指针不能进行解引用符操作,//所以先将他们强制类型转换为int*类型再进行解引用符操作}int i = 0;}原创 2022-09-07 12:20:44 · 306 阅读 · 0 评论 -
17.0、C语言——指针详解(3)
把 0 强制类型转换成一个 函数指针类型,该函数指针指向的函数是一个无参无返回值类型的函数,然后当 0 变成一个指针类型之后对他进行解引用操作,去调用以 0 为地址处的该函数。原创 2022-09-05 11:57:47 · 381 阅读 · 0 评论 -
16.0、C语言——指针详解(2)
当传递的参数是指针数组的首地址的时候,注意这里形参是一个二级指针,这里先回顾一下之前讲到 的指针定义的含义; 那么当一个指针数组作为参数传递给函数的时候,形参应该用二级指针 int** arr2 去接收,因为这里int*表示 arr2 指向的变量是一个 int* 类型的变量,第二个 ' * ' 表示这是一个指针变量,arr2 就是指针变量的名称一、中规中矩的写法:二、省略行的写法:【这里记住只能省略行不能省略列,否则编译不通过】三、用指针形参接收: 我们知道数原创 2022-08-27 15:14:21 · 339 阅读 · 0 评论 -
15.0、C语言——指针详解(1)
这里的 char* p = "abcdef"; 并不是说要将该字符串赋值给指针变量 p ,而是将该字符串的首地址存到 p 中(也就是将 a 的地址存进去),那么 第一个 printf 打印的是 %c 字符串,p存的是&a,那么*p就是a,所以结果的就是 a, 第二个 printf 打印的是 %s, 从a这个地址开始打印字符串直到 '\0' 处停止,结果出来的就是 abcdef 【这里注意:以这种形式创建字符串的话,那么"abcdef"就是常量字符串,不可更改,原创 2022-08-26 18:51:27 · 372 阅读 · 0 评论 -
14.0、C语言——数据存储(2)
但是我们知道,科学计数法中的 E 是可以出现负数的,所以 IEEE 754 规定,存入内存时 E 的真实值必须再加上一个中间数,对于 8 位的 E ,这个中间数是 127 ,对于 11 位的 E ,这个中间数是 1023。这样做的目的,是节省 1 位有效数字。举例来说:十进制的5.0,写成二进制是101.0,相当于 1.01× 2^2,那么按照上面v的格式,可以得出s = 0, M = 1.01, E = 2。对于32位的浮点数,最高的1位是符号位s,接着的8位是指数E,剩下的23位为有效数字M。原创 2022-08-23 13:35:50 · 231 阅读 · 0 评论 -
13.0、C语言——数据的存储(1)
1、内置类型【语言本身就具有的类型】2、自定义类型【构造类型】原创 2022-08-19 18:01:45 · 216 阅读 · 0 评论 -
12.0、C语言——实用调试技巧
发现程序错误的存在 以隔离、消除等方式对错误进行定位 确定错误产生的原因 提出纠正错误的解决方法 对程序错误予以改正,重新测试 写好代码点击运行后,会发现代码文件夹中多了一个Debug文件夹,点进去可以看到一个.exe文件,双击可以运行: 那么当我们选择Release再运行一次代码后,会发现多了一个Release文件夹,里面也有一个.exe文件,双击之后可以运行 vs最常用的几个快捷键: 下面来看一原创 2022-08-18 17:18:40 · 398 阅读 · 0 评论 -
11.0、C语言——初识结构体
因为如果使用传值的方式,设想一下如果我们的结构体中所有成员变量占用的内存空间为 200byte 或者 2000byte ,那么传递给形参的时候就会拷贝一份相同的数据给形参,这时候由于参数是需要压栈的,如果结构体过大,参数压栈的系统开销比较大,会导致性能下降;但是如果传递的是地址,也就是指针变量的话,那么传递过去的就仅仅是一个4byte或者8byte的地址,占用的内存空间大大减少,不会导致空间资源的浪费。结构的每个成员可以是不同类型的变量。结构体的成员可以是标量、数组、指针,甚至是其他结构体。...原创 2022-08-17 14:27:57 · 315 阅读 · 0 评论 -
10.0、C语言——初识指针(2)
1、指针 +- 整数 2、指针 - 指针 3、指针的关系运算指针减去指针: 得到的是两者中间减得到中间元素的个数,两个指针相减那么这两个指针一定指向同一块内存空间 不要用两个指向不同内存空间的指针互减(结果不可预知) 下面给大家举个例子: 自定义一个计算字符串大小的函数 my_strlen(char* arr); 定义两个指针变量一个start 一个 end; 接下来进行 whil原创 2022-08-15 11:47:59 · 262 阅读 · 0 评论 -
9.0、C语言——初识指针(1)
指针是一个变量,而这个变量存放的内容是地址,所以可以说地址就是指针,指针就是地址。原创 2022-08-15 07:16:01 · 297 阅读 · 0 评论 -
8.0、C语言——操作符
只有负数在算术右移运算时才会补 1 其他情况都是补 0;虽然有两种移位方式但是通常我们见到的都是算术右移;右移移位是除 2,左移一位是乘 2。原创 2022-08-13 17:17:17 · 538 阅读 · 0 评论 -
7.0、C语言——数组
往往我们在写代码的时候,会将数组作为参数传给函数,当我们将数组作为实参传递给函数形参的时候,不会把整个数组都传过去,【形参其实就是实参的一个临时拷贝的变量】假设数组有一万个元素,这时候如果将数组元素全部拷贝过去将会十分浪费资源和空间,所以只会将数组首个元素的地址传过去,然后由于数组的内存空间是连续的,只需要知道首地址就能够顺藤摸瓜的找到该数组剩下的所有元素了~可以把二维数组看成一维数组,例如我们可以把arr[0]看成是第一行数组的名字,然后后面跟的是[1/2/3/4]数组的下标。...原创 2022-08-09 14:22:18 · 486 阅读 · 0 评论 -
6.0、C语言——递归函数
程序调用自身的编程技巧称为递归(recursion),递归作为一种算法在程序设计语言中广泛应用。一个过程或函数在其定义或说明中有直接或简介调用自身的一种方法,他通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需要少量的程序就可描述出解题过程所需要多次重复的计算,大大减少了程序的代码量。递归的主要思考方式在于:把大事化小。...原创 2022-08-08 15:10:33 · 539 阅读 · 0 评论 -
5.0、C语言——函数
数学中我们常见到的函数的概念,但是你了解C语言中的函数吗?维基百科中对函数的定义:子程序C语言中函数的分类: 1.库函数 2.自定义函数 库函数:为什么会有库函数? 我们知道在学习C语言编程的时候,总是在一个代码编写完成之后迫不及待的想知道结果,想把这个结果打印到我们的屏幕上看看。这个时候我们会频繁的使用一个功能:将信息按照一定的格式打印到屏幕上(printf) 在编程的过程中我们会频繁的做一些字符串的拷贝工作(strcpy)原创 2022-08-06 14:10:42 · 564 阅读 · 0 评论 -
4.0、C语言——goto语句
C语言中提供了可以随意滥用的goto语句和标记跳转的标号【这里建议大家在写代码的过程中尽量不要使用 goto 语句,在实在没有办法的情况下再去使用】上图中有三个 for 嵌套循环,如果要跳出最外面那个for至少需要三个 break,但是 goto 语句只用这一句代码就可以直接跳出三层循环。但是某些场合下 goto 语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,例如一次跳出两层或多层循环。从理论上 goto 是没有必要的,实践中没有 goto 语句也可以很容易的写出代码。.....原创 2022-08-05 18:52:07 · 524 阅读 · 0 评论 -
3.0、C语言——猜数字游戏
时间戳 指的就是从 1970 年 1 月 1 日 0 时 0 点 0 分 开始算起,一直到当前时间的总秒数,这段数字就是时间戳,由于时间在不断的前进,所以时间戳也在不断的改变,这里再顺便说一下 由于以前的计算机操作系统只有 32位 所以时间戳最多间隔时间只能表示 68年,那么也就是说到了2038 便会达到最大时间,过了这个时间点所有的 32位 操作系统就会出现时间回归的现象 ->也就是全部重置为 10000000 00000000 00000000 00000000 很多软件就会出现异常了,...原创 2022-08-05 17:06:43 · 1195 阅读 · 0 评论 -
2.0、C语言——分支、循环语句
C语言循环、分支语句原创 2022-08-01 20:18:05 · 218 阅读 · 0 评论 -
1.0、C语言——初识C语言
C语言是一门面向过程的计算机编程语言,与C++、C#、Java等面向对象编程语言有所不同。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、仅产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。C语言描述问题比汇编语言迅速、工作量小、可读性好、易于调试、修改和移植,而代码质量与汇编语言相当。C语言一般只比汇编语言代码生成的目标程序效率低10%-20%。因此,C语言可以编写系统软件。[2]当前阶段,在编程领域中,C语言的运用非常之多,它兼顾了高级语言}..................原创 2022-07-26 15:41:19 · 620 阅读 · 1 评论