【C语言篇】☞ 16. 标准函数、预处理
C语言标准函数
1. 堆内存管理
- malloc函数(动态内存分配):在堆中分配指定大小的一段连续的内存空间,返回这片内存的首地址。(分配内存空间)
返回类型是 void* 类型,void* 表示未确定类型的指针。C,C++规定,void* 类型可以强制转换为任何其它类型的指针。
(提示:在C中void*可以不用强制转换,但在C++中一定要强转,否则编译不通过报错;便于程序能移植到C++中,建议养成强制转换的习惯)
- calloc函数:与malloc作用相同,只是默认会把分配到的所有字节都清零。(分配内存空间 + 初始化清零)
calloc()函数有两个参数,分别为元素的数目和每个元素的大小,这两个参数的乘积就是要分配的内存空间的大小。
- realloc函数:更改由malloc()函数分配的内存空间的大小。并将新的内存指针返回。
- 如果将分配的内存减少,realloc仅仅是改变索引的信息。
- 如果是将分配的内存扩大,则有以下情况:
-
如果当前内存段后面有需要的内存空间,则直接扩展这段内存空间,realloc()将返回原指针。
- 如果当前内存段后面的空闲字节不够,那么就使用堆中的第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,并将原来的数据块释放掉,返回新的内存块位置。
-
如果申请失败,将返回NULL,此时,原来的指针仍然有效。可以使用realloc函数对用malloc函数分配好的空间重新分配,一般是扩大。
-
- 注意:如果调用成功,不管当前内存段后面的空闲空间是否满足要求,都会释放掉原来的指针,重新返回一个指针,虽然返回的指针有可能和原来的指针一样,即不能再次释放掉原来的指针。
- free函数:释放内存空间
free(p); //释放指针p所指的内存空间
2. 标准输入输出
(1)控制台输入输出,可以接收用户从键盘上输入的数据
- scanf()在输入字符的时候存在缓冲区问题
通过scanf("%*c");清除缓冲区。
- scanf()和gets()在输入字符串的时候不存在缓冲区问题,但存在安全性问题(内存溢出)
- fgets()函数,解决安全性问题
- 语法格式:fgets(参数1,参数2,参数3);
- 参数1:保存数据的首位置
- 参数2:保存的长度(包括结束符)
- 参数3:stdin(标准控制台输入)
- 语法格式:fgets(参数1,参数2,参数3);
(2)格式化输入输出
- printf()可以输出字符串,并且可以根据占位符的个数来决定输出字符串的个数。
-
puts()可以输出一个字符串,而且是自动换行。
-
printf()与puts
-
相同点:都可以输出字符串
-
不同点:
-
printf()需要手动换行,可以多次输出字符
-
puts()自动换行,只能输出一次字符串内容
-
-
- const关键字:可以将变量变为只读,只可以在初始化时改变变量的值,此变量就为常量。
- const int*p = &i; //指针指向的值变为只读
- int *const p = &i; //指针的值变为只读
(3)数据类型之间的转换
- sprintf函数,可以将各种数据类型(整型、长整型、浮点型等)转换为字符串。
-
将字符串转换为任意类型(整型、长整型、浮点型等)。
- atof():将字符串转换为双精度浮点型值。
-
atoi():将字符串转换为整型值。
-
atol():将字符串转换为长整型值。
3. 其它库函数
(1)可变长参数
(2)日期和时间处理(time.h)
- 时间处理函数
clock函数
difftime函数
mktime函数
time函数
- 时间转换函数
asctime函数
ctime函数
gmtime函数
localtime函数
(3)内存清理与拷贝(string.h)
预处理
1. 预处理器
预处理器是一个程序,用来处理源程序中的预处理指令,一个源程序在编译前要先做预处理。
预处理:是将源程序中的预处理指令进行替换和处理。程序代码在提交给编译器之前,先将一些代码替换(预处理)
命令:gcc(clang) -E xxx.c //(-E)只做预处理
2. 预处理指令
预处理指令:以"#"开头的指令都是预处理指令。
如:#include, #define, 条件编译指令(#if, #ifdef, #ifndef, #endif...)
(可以出现在任何源程序位置,但必须一行结束,一条指令只能是一行。一行如果写不完,就用"\"换行)
(1)文件包含:#include <> 或 #include "" : 将一个文件中的内容复制到当前位置
#include在干什么:找到一个文件,将文件中的内容全部拷贝到此。(是预处理指令,由预处理器来处理的) #include <stdio.h> 和 #include " " <>的意思是从系统指定的位置查找文件。stdio.h是系统标准的头文件,保存在系统指定的位置,所以用<> “” 从当前目录查找文件,如果在当前目录下找不着,就再到系统指定的目录下找 |
(2)宏定义:#define 用来定义宏,宏是一种代码替换技术。
无参宏定义(简单的宏):只做简单的替换,提高程序的可读性和可维护性
#define PI 3.1415926 //定义了一个宏,名字是PI 用于替换3.14
(3)条件编译指令(#if, #ifdef, #ifndef, #endif, #elif, #else, #undef, #defined, #error)
条件编译指令将决定哪些代码被编译,而哪些是不被编译的。
在代码中设置编译条件,根据编译条件进行代码的编译并运行。(跨平台)
在编译文件的时候传入一个参数,根据参数就可以对代码进行有选择的编译。
#ifdef 和 #ifndef 这二者主要用于防止头文件重复包含。
#if defined 等价于 #ifdef; #if !defined 等价于 #ifndef