C语言
文章平均质量分 80
菜鸟学编程o
博客为个人学习记录
展开
-
文件输入/输出
文件通常是在磁盘或固态硬盘上的一段已命名的存储区。C把文件看作是一系列连续的字节,每个字节都能被单独读取。C提供两种文件模式:文本模式和二进制模式。原创 2024-05-22 12:00:00 · 793 阅读 · 0 评论 -
C结构详解
编译器执行这行代码便创建了一个结构变量library。编译器使用book模板为该变量分配空间。在结构变量的声明中,struct book 所起的作用相当于一般声明中的 int 或 float。}library;声明结构的过程和定义结构变量的过程可以组合成一个步骤,组合后的结构声明和结构变量定义不需要使用结构标记。然而,如果打算多次使用结构模板,就要使用带标记的形式。原创 2024-05-22 02:55:35 · 458 阅读 · 0 评论 -
其他标准I/O函数(fread、fwrite、feof、ferror)
当上一次输入调用检测到文件结尾时,feof()函数返回一个非零值,否则返回0.当读写出现错误时,ferror()函数返回一个非零值,否则返回0。假设要读取下一个冒号之前的所有字符,但是不包括冒号本身,可以使用getchar()或getc()函数读取字符到冒泡,然后用ungetc()函数把冒号放回输入流中。除此之外,它还包含错误和文件结尾的指示器、一个指向缓冲区开始出的指针、一个文件标识符和一个计数(统计实际拷贝进缓冲区的字节数)。当设置了与流关联的文件结束标识符时,该函数返回一个非零值,否则返回零。原创 2024-05-21 15:24:57 · 610 阅读 · 0 评论 -
编译和链接
编译是指将源代码(通常是人类可读的高级语言代码)转换成目标代码(通常是机器语言或汇编语言)的过程。编译器是完成这一转换的软件工具。预处理(预编译):在这个阶段,编译器会处理源代码中的预处理器指令,如包含头文件、宏展开等。词法分析:编译器将源代码分解成一系列的词法单元,如关键字、标识符、运算符、字面量等。语法分析:编译器检查词法单元序列是否符合编程语言的语法规则,构建抽象语法树(AST)。语义分析:编译器分析AST,确保代码的语义正确,比如变量是否已经定义、类型是否匹配等。中间代码生成。原创 2024-05-20 16:19:36 · 488 阅读 · 0 评论 -
联合和枚举
1、先定义枚举类型,再定义枚举变量enum DAY2、定义枚举类型的同时定义枚举变量enum DAY} day;3、省略枚举名称,直接定义枚举变量enum} day;return 0;结果:3在C 语言中,枚举类型是被当做 int 或者 unsigned int 类型来处理的,所以按照 C 语言规范是没有办法遍历枚举类型的。不过在一些特殊的情况下,枚举类型必须连续是可以实现有条件的遍历。原创 2024-04-22 23:07:17 · 680 阅读 · 0 评论 -
结构体的内存对齐
原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读会泽写值了。4、如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中 最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。VS中默认的值为8 Linux中gcc没有默认的对齐数,对齐数就是成员自身的大小。3、结构体总大小为最大对齐数(结构体中 每个成员变量都有一个对齐数,所有对齐数种最大的)的整数倍。原创 2024-04-15 22:12:19 · 486 阅读 · 0 评论 -
大小端字节序、浮点数的存储
这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为8bit位,参数在C语言中除了8bit的char之外,还有16bit的short类型,32bit的long类型(还要看具体的编译器)。如果E为11位,它的取值范围为0~2047.但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存是E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于32位的浮点数,最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M。原创 2024-04-15 18:35:01 · 681 阅读 · 1 评论 -
内存函数memcpy、mommove、memset、memcmp
但是在重叠内存块这方面,memmove() 是比 memcpy() 更安全的方法。如果目标区域和源区域有重叠的话,memmove() 能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,复制后源区域的内容会被更改。memset() 函数将指定的值 c 复制到 str 所指向的内存区域的前 n 个字节中,这可以用于将内存块清零或设置为特定值。在清空内存区域或者为内存区域赋值时,memset() 是一个常用的工具函数。该函数返回一个指向目标存储区 str1 的指针。用于将一段内存区域设置为指定的值。原创 2024-04-12 22:24:20 · 1052 阅读 · 0 评论 -
字符函数strlen、strcpy、strcat、strcmp、strstr、strtok、 strerror和perror函数
这个头文件中说明的,C语言程序启动的时候就会使用一个全面的变量 errno 来记录程序的当前错误码,只不过程序启动的时候 errno 是0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在 errno 中,而一个错误码的数字是整数很难理解是什么意思,所以每一个错误码都是有对应的错误信息的。haystack和needle分别指向字符串的首字母,如果找到相同的字符,haystack和needle向后移一位,如果没有找到相同的,haystack向后移一位。原创 2024-04-10 20:26:17 · 695 阅读 · 0 评论 -
函数指针数组
首先p要和[]先结合,我们拿掉数组名后剩下的就是数组的元素类型。也就是: int (*)() 函数指针。函数指针数组,我们通常也叫作转移表。1、不适用函数指针数组的转移表。2、使用函数指针数组实现转移表。函数指针数组的用途:转移表。如何创建函数指针数组?原创 2024-04-05 14:08:45 · 313 阅读 · 0 评论 -
深入理解指针2:数组名理解、一维数组传参本质、二级指针、指针数组和数组指针、函数中指针变量
这里我们发现&arr[0]和&arr[0]+1相差4个字节,arr和arr+1相差4个字节,是因为&arr[0]和 arr 都是首元素的地址,+1就是跳过1个元素。在数组传参的时候,传递的是数组名,也就是说本质上数组传参本质上传递的是数组首元素的地址。*(*(zippo+2) + 1) 二维数组的第 3个一维数组元素的第 2个int 类型元素的值,即数组的第3行第2。*(zippo+2) + 1 二维数组的第 3个元素(即一维数组)的第 2个元素(也是一个 int 类型的值)地址。原创 2024-04-04 23:24:55 · 964 阅读 · 0 评论 -
深入理解指针1:指针变量、指针运算、野指针、const修饰指针
生活中我们把门牌号也叫地址,在计算机中我们把内存单元的编号也称为地址。C语⾔中给地址起了新的名字叫:指针。所以我们可以理解为:内存单元的编号==地址==指针。原创 2024-04-01 23:46:41 · 550 阅读 · 0 评论 -
C按位操作符(~、&、|、^)
C提供按位逻辑运算符和移位运算符。原创 2024-01-21 14:18:20 · 1145 阅读 · 0 评论 -
ANSI C类型限定符(const、volatile)
C90 恒常性const 易变性 volatileC99 restrict 用于提高编译器优化C11 _Atomic C11提供一个可选库,由stdatomic.h管理,以支持并发程序设计,而且_Atomic是可选支持项。原创 2024-01-15 15:30:38 · 1270 阅读 · 0 评论 -
【C】存储类别(作用域、链接、存储期)
C提供了多种不同的模型或存储类别在内存中存储数据。从硬件方面来看,被存储的每个值都占有一定的物理内存,C语言把这样的一块内存称为对象。对象可以存储一个或多个值。一个对象可能并未存储实际的值,但是它在存储适当的值时一定具有相应的大小(面向对象编程中的对象指的是类对象,其定义包括数据和允许对数据进行的操作,C不是面向对象编程语言)。从软件方面看,程序需要一种方法访问对象。int a = 3;该声明创建了一个名为a的标识符。标识符可以用来指定对象的内容。原创 2024-01-13 09:15:53 · 1048 阅读 · 1 评论 -
动态内存分配函数——malloc、calloc、relloc
从ANSI C标准开始,C使用一个新的类型:指向void的指针。该类型相当于一个“通用指针”。malloc()函数可用于返回指向数组的指针、指向结构的指针等,所以通常该函数的返回值会被强制转化为匹配的类型。然而,把指向void的指针赋给任意类型的指针完全不用考虑类型匹配的问题。如果 malloc()分配内存失败,将返回空指针。我们试着用malloc()创建一个数组。除了用malloc在陈鼓型运行时请求一块内存,还需要一个指针记录着块内存的位置。原创 2024-01-14 09:26:07 · 1088 阅读 · 2 评论 -
内联函数(C99)
inline 的使用是有所限制的,inline 只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如 while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。:如果在每个文件里都实现一次该内联函数的话,那么,最好保证每个定义都是一样的,否则,将会引起未定义的行为。inline 函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联,并不是说声明了内联就会内联,声明内联只是一个建议而已。原创 2024-01-11 15:53:05 · 554 阅读 · 1 评论 -
可变参数:stdarg.h
然后,该函数将使用定义在stdarg.h中的va_start()宏,把参数列表拷贝到va_list类型的变量中。接着上面的例子讨论,va_list类型的变量是ap,parmN形参是lim。在上面的例子中,第1行f1()中parmN为n,第2行f2()中parmN为k。因为va_arg()不提供返回之前参数的方法,所以有必要保存va_list类型变量的副本。查看程序中的运算可以发现,第1次调用sum()时对3个数求和,第2次调用时对6个数求和。在该列中,lim是parmN形参,它表明变参列表中参数的数量。原创 2024-01-03 20:40:30 · 671 阅读 · 2 评论 -
C库——数学库和断言库
C标准规定了一些预定义宏C99新增inline关键字时,它是唯一的函数说明符(关键字extern和static是存储类别说明符,可应用于数据对象和函数)。C11新增了第2个函数说明符——Noreturn,表明调用完成后函数不返回主调函数。exit()函数是_Noreturn函数的一个示例,一旦调用exit,它不会再返回主调函数。size_t类型被定义为sizeof运算符的返回值类型——无符号整数类型,通常是unsigned int 或unsigned long。原创 2024-01-02 20:38:13 · 909 阅读 · 0 评论 -
C语言分支与循环1
C语言有3种循环,分别是for、while和do while循环。原创 2023-12-03 09:53:18 · 336 阅读 · 1 评论 -
C预处理器
假设先把 T 定义为20,稍后在该文件中又把它定义为25。这个过程称为重定义常量。不同的实现采用不同的重定义方案。除非新定义与旧定义相同,否则有些实现会将其视为错误,还有些会给出警告。ANSI标准采用第1种方案,只有新定义和旧定义完全相同才允许重定义。具有相同的定义意味着替换体中的记号必须相同,顺序也相同。//定义相同//这两条定义都有相同的记号,//额外的空格不算替换体的一部分//只有一个记号,因此与前两条定义不同。原创 2023-12-30 14:37:55 · 1400 阅读 · 1 评论 -
关于atexit()函数和exit()函数的用法——知识点总结
atexit()注册函数列表中的函数,当调用exit()时就会执行这些函数。最后调用exit()函数时,exit()会执行这些函数(执行顺序与列表中的函数顺序相反,即最先调用的是最后一个被注册的函数。即使没有显式调用exit(),main()结束时会隐式调用exit()。exit()执行完atexit()指定的函数后,会完成一些清理工作:刷新所有输出流,关闭所有打开的流和关闭标准I/O函数tmpfile()创建的临时文件。要使用atexit()函数,只需把退出时要调用的函数地址传递给atexit()即可。原创 2023-12-24 15:14:36 · 393 阅读 · 1 评论 -
泛型选择(简略)
Generic后面的圆括号中包含多个用逗号分隔的项。第1个项是一个表达式,后面的每个项都由一个类型、一个冒号和一个值组成,如 float: 1.第1个项的类型匹配哪个标签,整个表达式的值是该标签后面的值。例如,假设上面的表达式中x是int类型的变量,x的类型匹配int:标签,那么整个表达式的值就是0. 如果没有与类型匹配的标签,表达式的值就是default:标签后面的值.C11新增了一种表达式,叫作泛型选择表达式,可根据表达式的类型(即表达式的类型是int、double还是其他类型)选择一个值。原创 2023-12-24 23:20:48 · 398 阅读 · 1 评论 -
qsort()函数
必须把每个数组中每个元素的大小明确告诉qsort(),并且再比较函数的定义中,必须把该函数的指针参数转换为对具体应用而言类型正确的指针。第1个参数是指针,指向待排序数组的首元素。ANSI C允许va指向任何数据类型的指针强制转换成指向void的指针,因此,qsort()的第一个实际参数可以引用任何类型的数组。最后,qsort()还需要一个指向函数的指针,这个被指针指向的比较函数用于确定排序的顺序。表明qsort()最后一个参数是一个指向函数的指针,该函数返回int类型的值且接受两个指向。原创 2023-12-29 01:11:25 · 740 阅读 · 1 评论