C语言基础编程
Hello World
1 |
|
宏定义
宏定义是 C/C++ 语言中的一种预处理指令,用于在编译之前对代码进行文本替换。通过宏定义,可以定义常量、代码片段或者参数化的宏,以提高代码的可读性、可维护性以及复用性。
宏定义由 #define
指令实现,属于预处理阶段的内容。
1 |
示例
1 |
基本数据类型
char
长度:1字节
unsigned char
short
2字节
unsigned short
int
4字节
unsigned int
long
unsigned long
long long
8字节
unsigned long long
float
4字节
float
类型的变量需要在值后加f
或F
后缀,例如:3.14f
。double
8字节
void
运算符
1 | 算术运算符 |
流程控制
if
1 | if(expression){ |
1 | if(expression){ |
1 | if(expression){ |
switch
1 | switch (表达式) { |
while
1 | while (条件表达式) { |
do-while
1 | do { |
for
1 | for (初始化语句; 条件表达式; 更新语句) { |
continue
continue
用于跳过当前循环的剩余部分,直接进入下一次迭代。
break
用于跳出最近的循环或 switch
语句。
goto
数组
一维数组的定义方式
1 | int arr[10]; |
函数
1 | return_type function_name( parameter list ) |
指针
结构体
结构体(struct
)是一种用户自定义的数据类型,可以将不同类型的数据组合在一起,形成一个更复杂的数据结构。
结构体的定义与使用
访问结构体成员
通过点操作符 (.
) 来访问结构体的成员。
1 |
|
结构体指针
通过指针来访问结构体成员,使用箭头操作符 (->
) 来代替点操作符。
1 |
|
文件读写
C 语言的文件读写操作主要依赖 标准 I/O 库(stdio.h
),通过 FILE *
指针来管理文件。
fopen
1 | FILE *fopen(const char *filename, const char *mode); |
mode
模式 | 描述 |
---|---|
r | 打开一个已有的文本文件,允许读取文件。 |
w | 打开一个文本文件,允许写入文件。如果文件不存在,则会创建一个新文件。如果文件存在,则该会被截断为零长度,重新写入,会覆盖原来的内容。 |
a | 打开一个文本文件,以追加模式写入文件。如果文件不存在,则会创建一个新文件。 |
r+ | 打开一个文本文件,允许读写文件。 |
w+ | 打开一个文本文件,允许读写文件。如果文件已存在,则文件会被截断为零长度,如果文件不存在,则会创建一个新文件。 |
a+ | 打开一个文本文件,允许读写文件。如果文件不存在,则会创建一个新文件。读取会从文件的开头开始,写入则只能是追加模式。 |
write
fwrite()
将数据写入二进制文件
1 | size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream); |
fputc()
向文件写入一个字符。
1 | int fputc(int ch, FILE *stream); |
fputs()
将字符串写入文件。
1 | int fputs(const char *str, FILE *stream); |
fprintf()
将格式化数据写入文件。
1 | int fprintf(FILE *stream, const char *format, ...); |
read
fread()
从二进制文件读取数据
1 | size_t fread(void *ptr, size_t size, size_t count, FILE *stream); |
fgetc()
从文件读取一个字符。
1 | int fgetc(FILE *stream); |
fgets()
从文件读取一行字符串。
1 | char *fgets(char *str, int n, FILE *stream); |
fscanf()
从文件中读取格式化数据。
1 | int fscanf(FILE *stream, const char *format, ...); |
文件指针操作
ftell()
获取文件指针当前位置。
1 | long ftell(FILE *stream); |
fseek()
移动文件指针。
1 | int fseek(FILE *stream, long offset, int origin); |
rewind()
重置文件指针。
1 | void rewind(FILE *stream); |
将文件指针重置到文件开头(相当于 fseek(fp, 0, SEEK_SET);
)。
不会返回错误,也不会返回值。
内存分区
代码区
存放程序的机器指令,也就是程序的可执行代码。
静态区(全局区)
用于全局变量、静态变量和常量(全局常量、字符串常量)的存储。这部分内存的生命周期从程序开始直到程序结束。
栈(stack)
用于存储局部变量和函数调用时的上下文(如返回地址与参数等)。
堆(heap)
动态分配的内存区域,用于存放程序运行时动态创建的数据。
stdio.h
占位符
1 | %d 十进制有符号整数 |
库变量
size_t
无符号整数类型,它是 sizeof 关键字的结果。
1 | unsigned int |
FILE
文件流类型,适合存储文件流信息的对象类型。
fpos_t
文件位置类型,适合存储文件中任何位置的对象类型。
库函数
printf()
1 | int printf(const char *format, ...); |
sprintf()
用于将格式化的数据写入字符串。
1 | int sprintf(char *str, const char *format, ...); |
示例
1 |
|
snprintf()
用于将格式化的数据写入字符串。
1 | int snprintf(char *str, size_t size, const char *format, ...); |
示例
1 |
|
stdlib.h
库函数
calloc()
用于分配一块连续内存,并初始化为零。
1 | void* calloc(size_t num, size_t size); |
malloc()
用于动态分配指定字节数的内存空间,并返回指向这块内存的指针。内存内容未初始化,可能包含任意值(垃圾数据)。
1 | void* malloc(size_t size); |
realloc()
用于重新调整已经分配内存的大小。它可以增加或减少已分配内存的空间。
1 | void* realloc(void* ptr, size_t size); |
free()
用于释放由 malloc
、calloc
或 realloc
分配的动态内存,避免内存泄漏。
1 | void free(void* ptr); |
string.h
strlen()
用于计算字符串的长度。
1 | size_t strlen(const char *str); |
memset()
用于将一块内存区域的内容设置为指定的值。
1 | void* memset(void* ptr, int value, size_t num); |
memcmp()
1 | int memcmp(const void *s1, const void *s2, size_t n); |
如果返回 0,则表示前 n
个字节内的内容相同。
如果返回非 0 值,则表示存在不同的字节。其具体含义为:
- 返回一个 负值,表示在第一个不同的字节处,
s1
的值小于s2
中对应字节的值。 - 返回一个 正值,表示在第一个不同的字节处,
s1
的值大于s2
中对应字节的值。
比较时,memcmp
会将每个字节当作 unsigned char
来处理,这样可以避免因为符号位的不同而导致的比较问题。
memcpy()
通过逐字节复制的方式将一块内存数据从源地址拷贝到目标地址
1 | void *memcpy(void *dest, const void *src, size_t n); |
返回目标地址 dest
的指针。
strdup()
动态分配内存,并将字符串 s
的内容复制到新分配的内存中。
1 | char *strdup(const char *s); |
time.h
库变量
size_t
无符号整型,sizeof运算符的结果。
1 | unsigned int |
clock_t
表示处理器的时钟周期数。
1 | typedef long clock_t; // 或者 |
time_t
用于存储时间戳
1 | typedef long time_t; //或者 |
struct tm
tm 是一个结构体类型,用于表示具体的时间信息,通常是通过将时间戳(time_t)转换成更易于理解和操作的日期和时间格式。
1 | struct tm { |
库函数
time()
time()
函数用于获取当前时间戳。
1 | time_t time(time_t *timer); |
- 如果参数为NULL或0,返回当前时间的time_t值。
- 如果传递一个有效指针,函数会将当前时间保存到指针所指向的变量中,并返回相同的值。
localtime()
用于将 time_t 类型的时间值转换为结构化的本地时间格式(struct tm)。
1 | struct tm* localtime(const time_t* timer); |
将 time_t 类型的时间转换为本地时间,返回一个 struct tm 结构,表示本地时间的各个组成部分(年、月、日、小时、分钟、秒等)。
localtime_r()
用于将 time_t 类型的时间值转换为结构化的本地时间格式(struct tm)。
由于它将结果存储在用户提供的缓冲区中,多个线程可以同时调用 localtime_r 而不会发生冲突,因此它是线程安全的。
1 | struct tm* localtime_r(const time_t* timer, struct tm* buf); |
localtime_s()
localtime_s 是 C11 标准引入的函数,功能和 localtime_r 类似。它将 time_t 转换为本地时间,并将结果存储在用户提供的缓冲区中。
1 | struct tm* localtime_s(const time_t* restrict timer, struct tm* restrict buf); |
localtime_s 在 C11 标准中引入时,具有更严格的错误检查。如果出现错误(例如无效的时间值),通常会返回一个错误码,而不是直接返回 NULL。这增加了函数的安全性和可靠性。
pthread.h
库函数
pthread_create()
用于创建一个新的线程。
1 | int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg); |
pthread_t *thread
:
指向 pthread_t 类型的指针,用于存储新创建线程的线程 ID。const pthread_attr_t *attr
:
指向线程属性对象的指针,可以是 NULL,表示使用默认属性。void *(*start_routine)(void *)
:
线程的起始函数,这是一个函数指针,它指向一个函数,该函数接收一个 void * 类型的参数,并返回一个 void * 类型的值。void *arg
:
传递给起始函数的参数。返回值
成功返回0,否则返回错误码。
sched.h
clone
1 | // 系统调用版本(低级别) |
示例
1 |
|
sys/ptrace.h
ptrace()
ptrace
是 Unix/Linux 系统中用于进程跟踪(tracing)和调试的重要系统调用,它允许一个进程(通常是调试器)控制和监视另一个进程(通常是被调试的子进程)的执行情况,包括读取和修改目标进程的内存、寄存器等信息。
1 |
|