引言
上篇介绍了 ThreadPoolExecutor
配置和扩展相关的信息,本篇开始将介绍递归算法的并行化。
还记得我们在《Java并发编程学习11-任务执行演示》中,对页面绘制程序进行一系列改进,这些改进大大地提供了页面绘制的并行性。
上篇介绍了 ThreadPoolExecutor
配置和扩展相关的信息,本篇开始将介绍递归算法的并行化。
还记得我们在《Java并发编程学习11-任务执行演示》中,对页面绘制程序进行一系列改进,这些改进大大地提供了页面绘制的并行性。
函数声明 | 函数功能 |
---|---|
void perror(const char *s); |
用于将当前错误码对应的错误信息打印到标准输出设备(通常是终端)。 |
void pieslice(int x, int y, int stanle, int endangle, int radius); |
在图形模式下绘制并填充一个扇形(饼图切片) |
double pow(double x, double y); |
用于计算 x 的 y 次幂,并返回结果(double) |
float powf(float x, float y); |
用于计算 x 的 y 次幂,并返回结果(float) |
long double powl(long double x, long double y); |
用于计算 x 的 y 次幂,并返回结果(long double) |
double pow10(double x); |
用于计算 $10^x$ (double) |
float pow10f(float x); |
用于计算 $10^x$(float) |
long double pow10l(long double x); |
用于计算 $10^x$ (long double) |
int printf(const char *format, ...); |
它是标准 I/O 库中定义的函数,用于将格式化的数据输出到标准输出流(通常是控制台窗口) |
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); |
创建一个新的线程 |
int pthread_join(pthread_t thread, void **retval); |
阻塞当前线程,等待指定的线程结束。 |
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); |
初始化互斥锁。返回值为 0 表示成功,否则表示失败。 |
int pthread_mutex_destroy(pthread_mutex_t *mutex); |
销毁互斥锁。返回值为 0 表示成功,否则表示失败。 |
int pthread_mutex_lock(pthread_mutex_t *mutex); |
尝试获取互斥锁,如果已经被占用,则会阻塞当前线程。返回值为 0 表示成功获取互斥锁,否则表示失败。 |
int pthread_mutex_unlock(pthread_mutex_t *mutex); |
释放互斥锁。 |
int putc(int c, FILE *stream); |
它是标准 I/O 库中定义的函数,用于将一个字符输出到指定的文件流。 |
int putchar(int c); |
它是标准 I/O 库中定义的函数,用于将一个字符输出到标准输出流(通常是控制台窗口)。 |
int putenv(char *string); |
用于设置环境变量的值。 |
void putimage(int left, int top, void *bitmap, int op); |
用于将位图图像输出到指定的窗口或屏幕上 |
void putpixel(int x, int y, int color); |
用于将一个像素点画在指定的位置上 |
int puts(const char *s); |
用于将一个字符串输出到标准输出流 |
int putw(int w, FILE *stream); |
用于将一个整数值以二进制形式写入到指定的文件中。 |
函数声明 | 函数功能 |
---|---|
void perror(const char *s); |
用于将当前错误码对应的错误信息打印到标准输出设备(通常是终端)。 |
参数:
1 |
|
在上述的示例中,
fopen()
函数返回的值来检查是否成功。由于该文件不存在,fopen()
函数将返回 NULL
;perror()
函数来输出一个错误消息和具体的错误信息,以帮助我们找到问题所在。如果发生了错误,errno
全局变量会被设置为一个非零值,我们还可以使用它来获取具体的错误代码。函数声明 | 函数功能 |
---|---|
void pieslice(int x, int y, int stanle, int endangle, int radius); |
在图形模式下绘制并填充一个扇形(饼图切片) |
参数:
- radius : 圆的半径
1 |
|
函数声明 | 函数功能 |
---|---|
double pow(double x, double y); |
用于计算 x 的 y 次幂,并返回结果(double) |
float powf(float x, float y); |
用于计算 x 的 y 次幂,并返回结果(float) |
long double powl(long double x, long double y); |
用于计算 x 的 y 次幂,并返回结果(long double) |
1 |
|
函数声明 | 函数功能 |
---|---|
double pow10(double x); |
用于计算 $10^x$ (double) |
float pow10f(float x); |
用于计算 $10^x$(float) |
long double pow10l(long double x); |
用于计算 $10^x$ (long double) |
1 |
|
1 |
|
函数声明 | 函数功能 |
---|---|
int printf(const char *format, ...); |
它是标准 I/O 库中定义的函数,用于将格式化的数据输出到标准输出流(通常是控制台窗口) |
参数: |
返回值 :
1 |
|
函数声明 | 函数功能 |
---|---|
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); |
创建一个新的线程 |
int pthread_join(pthread_t thread, void **retval); |
阻塞当前线程,等待指定的线程结束。 |
pthread_create 参数:
NULL
表示使用默认属性pthread_join 参数:
pthread_t thread
:目标线程的标识符(由 pthread_create() 返回)。必须是已创建且未被分离(non-detached)的线程。void **retval
:用于接收目标线程的退出状态值的指针的地址。return
返回值或调用 pthread_exit(void *retval)
终止,retval
将指向该值。NULL
。retval
会被设为 PTHREAD_CANCELED
(通常为 -1)。1 |
|
在上述的示例中,主线程调用了 pthread_create()
函数来创建一个新的线程,并传递一个函数指针 thread_func
作为新线程的入口点。新线程运行这个函数,并输出一条消息。主线程等待新线程结束,然后继续运行自己的代码。
函数声明 | 函数功能 |
---|---|
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); |
初始化互斥锁。返回值为 0 表示成功,否则表示失败。 |
int pthread_mutex_destroy(pthread_mutex_t *mutex); |
销毁互斥锁。返回值为 0 表示成功,否则表示失败。 |
int pthread_mutex_lock(pthread_mutex_t *mutex); |
尝试获取互斥锁,如果已经被占用,则会阻塞当前线程。返回值为 0 表示成功获取互斥锁,否则表示失败。 |
int pthread_mutex_unlock(pthread_mutex_t *mutex); |
释放互斥锁。 |
参数:
NULL
表示使用默认属性。1 |
|
在上述的示例中,两个线程分别调用了 pthread_mutex_lock()
和 pthread_mutex_unlock()
函数来保护临界区代码,以确保同时只有一个。
函数声明 | 函数功能 |
---|---|
int putc(int c, FILE *stream); |
它是标准 I/O 库中定义的函数,用于将一个字符输出到指定的文件流。 |
参数:
返回值:
1 |
|
在上述的示例中,我们打开名为 output.txt
的文件以供写入,并使用 putc()
函数将字符串中的每个字符逐一输出到文件中。最后,我们关闭文件。
注意: 与
putchar()
函数类似,putc()
函数可以用来逐一输出字符串中的每个字符,但通常会更多地用于将数据写入文件或其他输出流。
函数声明 | 函数功能 |
---|---|
int putchar(int c); |
它是标准 I/O 库中定义的函数,用于将一个字符输出到标准输出流(通常是控制台窗口)。 |
参数:
返回值 :
1 |
|
注意: 单引号用于表示字符常量,例如 ‘H’ 表示字符 H 的 ASCII 码。
函数声明 | 函数功能 |
---|---|
int putenv(char *string); |
用于设置环境变量的值。 |
参数:
返回值:
0
表示成功;0
表示失败。1 |
|
在上述的示例中,
putenv()
函数将一个名为 MY_VAR 的环境变量设置为字符串 "hello"
。getenv()
函数获取 MY_VAR
环境变量的值;printf()
函数输出它。注意: 由于
putenv()
函数接受一个指向可变字符串的指针,因此应该避免将局部变量的地址传递给它,以免在函数返回后出现未定义行为。
函数声明 | 函数功能 |
---|---|
void putimage(int left, int top, void *bitmap, int op); |
用于将位图图像输出到指定的窗口或屏幕上 |
参数:
x
坐标y
坐标COPY_PUT
:覆盖模式,即将位图完全覆盖到目标位置。AND_PUT
:按位与模式,即将位图与目标位置进行按位与运算后输出。OR_PUT
:按位或模式,即将位图与目标位置进行按位或运算后输出。XOR_PUT
:按位异或模式,即将位图与目标位置进行按位异或运算后输出。1 |
|
上述程序使用了 graphics.h
图形库来画一个箭头,并在屏幕上循环移动它。
getmaxx()
和 getmaxy()
函数获取屏幕的宽度和高度。draw_arrow()
函数来绘制箭头图形,并使用 imagesize()
函数计算出需要分配给位图数据的内存大小。malloc()
函数动态分配了一块内存空间,并调用 getimage()
函数获取箭头图像的位图数据。该函数会将指定位置的屏幕区域保存到指定的内存地址中。putimage()
函数将之前存储的箭头图像覆盖掉屏幕上的箭头,然后将箭头向右移动一定的距离。当用户按下任意键时,程序结束循环并退出。函数声明 | 函数功能 |
---|---|
void putpixel(int x, int y, int color); |
用于将一个像素点画在指定的位置上 |
参数:
x
坐标y
坐标1 |
|
上述这个程序使用 graphics.h
图形库在屏幕上绘制随机像素点,并不断更新它们的颜色。
getmaxx()
、getmaxy()
和 getmaxcolor()
函数获取屏幕的尺寸和颜色范围。rand()
函数生成随机的坐标和颜色值,并使用 putpixel()
函数绘制对应位置的像素点。另外还使用了 delay()
函数来控制每次更新之间的时间间隔,该函数会使程序暂停指定的毫秒数,以便让用户观察到像素点的变化效果。函数声明 | 函数功能 |
---|---|
int puts(const char *s); |
用于将一个字符串输出到标准输出流 |
参数:
'\0'
结尾的字符串返回值:
1 |
|
注意: 在输出字符串时,
puts()
函数会自动将字符串的内容和换行符写入到标准输出流中,因此不需要再进行额外的操作。如果要将字符串输出到文件或其他输出流中,则可以使用fputs()
函数。
函数声明 | 函数功能 |
---|---|
int putw(int w, FILE *stream); |
用于将一个整数值以二进制形式写入到指定的文件中。 |
参数:
返回值:
4
个字节);EOF
。1 |
|
在上述的示例中,
fopen()
函数打开一个名为 "output.bin"
的二进制文件;putw()
函数将整数值写入到该文件中;注意: 由于
putw()
函数是以二进制形式写入数据的,因此相对于文本文件而言,它更适合用于存储数字、结构体等复杂类型的数据。如果要将字符串或其他文本数据写入到文件中,则可以使用fprintf()
函数。
函数声明 | 函数功能 |
---|---|
void obstack_init(struct obstack *obstack_ptr); |
它是 POSIX 标准库中的一个非标准函数,用于初始化对象堆栈。对象堆栈是一种可以动态增长以存储任意类型的对象的数据结构。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要初始化的对象堆栈。 |
void obstack_free(struct obstack *obstack_ptr, void *object_ptr); |
用于释放通过对象堆栈分配的所有内存。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要释放的对象堆栈;object_ptr 参数是要释放的内存块。 |
void *obstack_alloc(struct obstack *obstack_ptr, int size); |
用于从对象堆栈中分配指定大小的内存,并返回其地址。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要从中分配内存的对象堆栈;size 参数表示要分配的内存块的大小。 |
void *obstack_blank(struct obstack *obstack_ptr, int size); |
用于向对象堆栈添加指定数量的空间,并返回指向添加的第一个字节的指针。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要添加空间的对象堆栈;size 参数表示要添加的空间大小。 |
void *obstack_grow(struct obstack *obstack_ptr, const void *data, int size); |
用于将数据复制到对象堆栈,并返回指向添加的第一个字节的指针。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要添加数据的对象堆栈;data 参数是要复制的数据的指针;size 参数表示要复制的数据的大小。 |
#define offsetof(type, member) ((size_t)(&((type *)0)->member)) |
它是一个宏,用于获取结构体中某个成员的偏移量。 |
int open(const char *path, int oflag, ...); |
用于打开文件 |
int openat(int dirfd, const char *pathname, int flags, mode_t mode); |
它是 Linux 系统定义的一个函数,它可以打开一个相对于指定目录的文件。与 open() 函数相比,openat() 函数更加灵活,并支持更多的选项。 |
DIR *opendir(const char *name); |
它是 POSIX 标准定义的一个函数,用于打开目录并返回一个指向 DIR 结构体类型的指针。 |
int openpty(int *amaster, int *aslave, char *name, const struct termios *termp, const struct winsize *winp); |
它是 POSIX 标准定义的一个函数,用于打开一个伪终端(PTY)并返回与之关联的主从设备文件描述符。伪终端可以用于在进程之间建立通信,或者在程序中模拟终端行为。 |
int on_exit(void (*function)(int, void *), void *arg); |
它是 POSIX 标准定义的一个函数,用于在进程退出时调用注册的回调函数。这个函数可以用于在程序异常退出或者正常退出时执行一些清理工作、记录日志等操作 |
void outtext(char *textstring); |
在图形视区显示一个字符串 |
void outtextxy(int x, int y, char *textstring); |
在指定位置显示一字符串 |
函数声明 | 函数功能 |
---|---|
void obstack_init(struct obstack *obstack_ptr); |
它是 POSIX 标准库中的一个非标准函数,用于初始化对象堆栈。对象堆栈是一种可以动态增长以存储任意类型的对象的数据结构。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要初始化的对象堆栈。 |
void obstack_free(struct obstack *obstack_ptr, void *object_ptr); |
用于释放通过对象堆栈分配的所有内存。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要释放的对象堆栈;object_ptr 参数是要释放的内存块。 |
void *obstack_alloc(struct obstack *obstack_ptr, int size); |
用于从对象堆栈中分配指定大小的内存,并返回其地址。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要从中分配内存的对象堆栈;size 参数表示要分配的内存块的大小。 |
void *obstack_blank(struct obstack *obstack_ptr, int size); |
用于向对象堆栈添加指定数量的空间,并返回指向添加的第一个字节的指针。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要添加空间的对象堆栈;size 参数表示要添加的空间大小。 |
void *obstack_grow(struct obstack *obstack_ptr, const void *data, int size); |
用于将数据复制到对象堆栈,并返回指向添加的第一个字节的指针。其中,obstack_ptr 参数是一个指向 struct obstack 类型的指针,表示要添加数据的对象堆栈;data 参数是要复制的数据的指针;size 参数表示要复制的数据的大小。 |
1 |
|
在上述的程序中,
my_obstack
的 struct obstack
类型变量,并将其传递给 obstack_init()
函数以初始化对象堆栈。obstack_alloc()
函数从对象堆栈中分配一块内存,并将两个字符串连接起来。obstack_blank()
函数向对象堆栈添加一块指定大小的空间,并使用 memcpy()
函数将两个整数复制到该空间中。obstack_grow()
函数向对象堆栈添加一个双精度浮点数,并返回指向该浮点数的指针。printf()
函数将连接后的字符串、添加的整数和添加的双精度浮点数输出到终端,并使用 obstack_free()
函数释放通过对象堆栈分配的所有内存。注意:在使用
obstack_blank()
函数向对象堆栈添加空间时,建议使用sizeof
运算符来计算要添加的空间大小,并在使用memcpy()
复制数据时也应该小心不要越界。同时,在使用obstack_grow()
函数向对象堆栈添加数据时,需要小心指针是否正确,并且操作前需要先使用memcpy()
将要添加的数据复制到一个临时变量中。
宏定义 | 宏描述 |
---|---|
#define offsetof(type, member) ((size_t)(&((type *)0)->member)) |
它是一个宏,用于获取结构体中某个成员的偏移量。 |
参数:
返回值: 一个 size_t 类型的值,表示该成员变量在结构体中的偏移量(单位是字节)。
1 |
|
在这个程序中,
example
的结构体类型,并使用 offsetof
宏获取结构体中成员变量 b
的偏移量。printf()
函数将结果输出到终端。注意: 在使用
offsetof
宏时,结构体类型名称必须使用括号括起来,否则代码会产生语法错误。此外,offsetof
宏的参数必须是已定义的结构体类型名称和该结构体类型中的成员变量名称,否则也会导致编译错误。
函数声明 | 函数功能 |
---|---|
int open(const char *path, int oflag, ...); |
用于打开文件 |
参数:
O_RDONLY
:只读模式打开文件。O_WRONLY
:只写模式打开文件。O_RDWR
:读写模式打开文件。O_CREAT
:如果文件不存在,则创建它。O_TRUNC
:如果文件已存在,则将其长度截断为 0。O_APPEND
:在文件末尾追加数据。O_CREAT
选项,则必须提供这个参数1 |
|
在上述的程序中,
open()
函数打开文件 temp.txt
,并通过 read()
函数读取其中的数据。write()
函数将数据写入标准输出,直到读取完整个文件。close()
函数关闭文件。注意: 在使用
open()
函数打开文件时,返回值为负数则表示出现了错误。此时可以使用perror()
函数输出错误信息,并使用exit()
函数退出程序。同时,在使用read()
函数和write()
函数读写文件时也需要小心处理返回值,以避免出现不可预期的错误。
函数声明 | 函数功能 |
---|---|
int openat(int dirfd, const char *pathname, int flags, mode_t mode); |
它是 Linux 系统定义的一个函数,它可以打开一个相对于指定目录的文件。与 open() 函数相比,openat() 函数更加灵活,并支持更多的选项。 |
参数:
AT_FDCWD
,则表示使用当前工作目录。O_RDONLY
:只读模式打开文件。O_WRONLY
:只写模式打开文件。O_RDWR
:读写模式打开文件。O_CREAT
:如果文件不存在,则创建它。O_TRUNC
:如果文件已存在,则将其长度截断为 0。O_APPEND
:在文件末尾追加数据。O_DIRECTORY
:要求打开的文件必须是一个目录。O_NOFOLLOW
:不跟随符号链接打开文件。O_CREAT
选项,则必须提供这个参数1 |
|
在这个程序中,
openat()
函数打开当前目录,并通过 fdopendir()
函数将文件描述符转换为目录流。readdir()
函数读取目录中的文件,并将文件名输出到终端。closedir()
函数关闭目录。注意: 在使用
openat()
函数打开文件时,可以通过传递不同的文件描述符指定要打开的目录,从而实现更加灵活的操作。此外,在使用readdir()
函数读取目录时也需要注意判断返回值是否为NULL
,以避免出现不可预期的错误。
函数声明 | 函数功能 |
---|---|
DIR *opendir(const char *name); |
它是 POSIX 标准定义的一个函数,用于打开目录并返回一个指向 DIR 结构体类型的指针。 |
参数:
返回值:
DIR
类型的指针;NULL
。1 |
|
在上述的程序中,我们使用 opendir()
函数打开当前目录,并通过 readdir()
函数读取目录中的文件名,最后使用 closedir()
函数关闭目录。
注意: 在使用
opendir()
函数打开目录时,返回值为NULL
则表示出现了错误。此时可以使用perror()
函数输出错误信息,并使用exit()
函数退出程序。同时,在使用readdir()
函数读取目录时也需要小心处理返回值,以避免出现不可预期的错误。
函数声明 | 函数功能 |
---|---|
int openpty(int *amaster, int *aslave, char *name, const struct termios *termp, const struct winsize *winp); |
它是 POSIX 标准定义的一个函数,用于打开一个伪终端(PTY)并返回与之关联的主从设备文件描述符。伪终端可以用于在进程之间建立通信,或者在程序中模拟终端行为。 |
参数:
NULL
NULL
NULL
返回值:
0
;-1
。1 |
|
在上述的程序中,
openpty()
函数打开一个伪终端,并通过 read()
函数读取标准输入中的数据。注意: 在使用
openpty()
函数打开伪终端时,返回值为-1
则表示出现了错误。此时可以使用perror()
函数输出错误信息,并使用exit()
函数退出程序。同时,在使用read()
函数和write()
函数读写文件时也需要小心处理返回值,以避免出现不可预期的错误。
函数声明 | 函数功能 |
---|---|
int on_exit(void (*function)(int, void *), void *arg); |
它是 POSIX 标准定义的一个函数,用于在进程退出时调用注册的回调函数。这个函数可以用于在程序异常退出或者正常退出时执行一些清理工作、记录日志等操作 |
参数:
返回值:
0
;-1
。1 |
|
在如上的程序中,
on_exit()
函数注册了一个回调函数 cleanup()
,并将其参数设置为 NULL。函数声明 | 函数功能 |
---|---|
void outtext(char *textstring); |
在图形视区显示一个字符串 |
参数:
char *textstring
:指向以空字符(’\0’)结尾的字符串的指针。1 |
|
在上述的程序中,
initgraph()
函数初始化图形系统;moveto()
函数将当前绘图位置移动到屏幕中心。outtext()
函数输出一段文字,然后等待用户按下任意键,并关闭图形窗口。函数声明 | 函数功能 |
---|---|
void outtextxy(int x, int y, char *textstring); |
在指定位置显示一字符串 |
参数:
int x
: 字符串输出的水平起始坐标(单位为像素)。取值范围:与当前图形模式的屏幕分辨率相关(例如,640x480 模式下,x 范围为 0 到 639)。
int y
: 字符串输出的垂直起始坐标(单位为像素)。取值范围:与当前图形模式的屏幕分辨率相关(例如,480p 模式下,y 范围为 0 到 479)。
char *textstring
: 指向以空字符(’\0’)结尾的字符串的指针。
1 |
|
在上述这个程序中,
initgraph()
函数初始化图形系统并创建一个窗口;(x, y)
并使用 outtextxy()
函数在该位置输出一段文本。getch
函数等待用户按下任意键,然后关闭图形窗口。函数声明 | 函数功能 |
---|---|
double nan(const char *tagp); |
用于返回一个表示 NaN(非数值)的 double 类型数字 |
int nanosleep(const struct timespec *req, struct timespec *rem); |
用于暂停当前进程的执行一段指定的时间。相比于 sleep() 函数,nanosleep() 函数可以精确地指定等待时间,以纳秒为单位。 |
double nearbyint(double x); |
用于将一个浮点数四舍五入到最接近的整数值(double) |
float nearbyintf(float x); |
用于将一个浮点数四舍五入到最接近的整数值(float) |
long double nearbyintl(long double x); |
用于将一个浮点数四舍五入到最接近的整数值(long double) |
double nextafter(double x, double y); |
用于找出与给定的浮点数最接近的下一个浮点数(double) |
float nextafterf(float x, float y); |
用于找出与给定的浮点数最接近的下一个浮点数(float) |
long double nextafterl(long double x, long double y); |
用于找出与给定的浮点数最接近的下一个浮点数(long double) |
double nexttoward(double x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(double) |
float nexttowardf(float x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(float) |
long double nexttowardl(long double x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(long double) |
locale_t newlocale(int category_mask, const char *locale, locale_t base); |
用于创建并返回一个新的本地化环境变量,以便在不同的本地化设置之间进行切换。 |
int nftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf), int nopenfd, int flags); |
用于递归遍历指定目录下的所有文件和子目录,并对每个文件或目录执行指定操作。 |
int nice(int inc); |
它是一个系统调用,可将进程截止到当前用户的最大优先级减少指定的优先级,以更改进程的调度优先级。较高的 niceness 值意味着较低的优先级。 |
char *nl_langinfo(nl_item item); |
它是一个 POSIX 标准函数,用于获取当前本地化环境下的语言环境信息。它可以返回一些与语言、货币、日期和时间格式等相关的信息。 |
long nrand48(unsigned short xsubi[3]); |
用于生成带有指定状态的随机数。它使用 48 位整数来表示随机数的状态,可以方便地切换不同的随机数生成器状态。 |
uint32_t ntohl(uint32_t netlong); |
用于将网络字节序(大端序)转换为主机字节序(小端序)。 |
uint16_t ntohs(uint16_t netshort); |
用于将网络字节序(大端序)转换为主机字节序(小端序)。 |
函数声明 | 函数功能 |
---|---|
double nan(const char *tagp); |
用于返回一个表示 NaN(非数值)的 double 类型数字 |
参数:
1 |
|
注意:
NaN
数字具有一些特殊的属性,例如与任何数字进行比较都会返回false
,因此在实际编程中需要特别小心处理NaN
的情况,避免出现异常结果
函数声明 | 函数功能 |
---|---|
int nanosleep(const struct timespec *req, struct timespec *rem); |
用于暂停当前进程的执行一段指定的时间。相比于 sleep() 函数,nanosleep() 函数可以精确地指定等待时间,以纳秒为单位。 |
参数:
timespec
结构体包含两个成员变量:tv_sec
表示等待时间的整数部分(秒),tv_nsec
表示等待时间的小数部分(纳秒)。如果 rem
参数不为 NULL
,则在函数返回时,未完成的等待时间将被存储在 rem
指向的 timespec
结构体中。1 |
|
在上述的程序中,
timespec
结构体变量 req
,用于指定等待时间。在本例中,我们将等待时间设置为 2
秒加上 5
毫秒。nanosleep()
函数,并传递 req
变量的地址作为第一个参数。如果函数执行成功(即完成了预定的等待时间),则返回值为 0
,否则返回 -1
。nanosleep()
是否成功完成。如果返回值为 0
,则表示函数已经完成了预定的等待时间;如果返回值为 -1
,则说明函数被信号中断。在实际编程中,我们还可以通过检查 errno
变量来获取更具体的错误信息。函数声明 | 函数功能 |
---|---|
double nearbyint(double x); |
用于将一个浮点数四舍五入到最接近的整数值(double) |
float nearbyintf(float x); |
用于将一个浮点数四舍五入到最接近的整数值(float) |
long double nearbyintl(long double x); |
用于将一个浮点数四舍五入到最接近的整数值(long double) |
1 |
|
注意:
nearbyint()
函数对于0.5
的情况具有特殊处理:如果要转换的数恰好与两个整数的距离相等,则按照偶数方向进行舍入(即选择更接近偶数的整数)。例如,如果要将2.5
转换为整数,那么将近似到最接近的偶数2
,而不是3
。这种舍入方式称为 “银行家舍入法” 或 “四舍六入五成双”。
函数声明 | 函数功能 |
---|---|
double nextafter(double x, double y); |
用于找出与给定的浮点数最接近的下一个浮点数(double) |
float nextafterf(float x, float y); |
用于找出与给定的浮点数最接近的下一个浮点数(float) |
long double nextafterl(long double x, long double y); |
用于找出与给定的浮点数最接近的下一个浮点数(long double) |
参数:
- y : 给定浮点数的目标值,表示前进方向。
返回值:
y
大于 x
,则向正无穷方向查找;y
小于 x
,则向负无穷方向查找;如果 y
等于 x
,则返回 y
。1 |
|
注意: 由于计算机内部存储浮点数的方式是有限制的,因此在进行浮点数计算时可能会存在误差。在实际编程中,我们应该特别小心处理这些情况,避免出现异常结果。
函数声明 | 函数功能 |
---|---|
double nexttoward(double x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(double) |
float nexttowardf(float x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(float) |
long double nexttowardl(long double x, long double y); |
用于找出与给定的浮点数最接近、并朝着指定方向的下一个浮点数(long double) |
参数:
返回值:
y
大于 x
,则向正无穷方向查找;y
小于 x
,则向负无穷方向查找;如果 y
等于 x
,则返回 y
。1 |
|
函数声明 | 函数功能 |
---|---|
locale_t newlocale(int category_mask, const char *locale, locale_t base); |
用于创建并返回一个新的本地化环境变量,以便在不同的本地化设置之间进行切换。 |
参数:
LC_ALL_MASK
:表示所有类别。LC_COLLATE_MASK
:表示字符串比较和排序规则。LC_CTYPE_MASK
:表示字符分类和转换规则。LC_MESSAGES_MASK
:表示本地化消息文本。LC_MONETARY_MASK
:表示货币格式。LC_NUMERIC_MASK
:表示数字格式。LC_TIME_MASK
:表示时间和日期格式。NULL
或空字符串,则使用当前系统默认的本地化设置。NULL
,则使用 LC_GLOBAL_LOCALE
。1 |
|
在上述程序中,
newlocale()
函数创建一个新的本地化环境变量 loc
,以便比较和排序德语字符串。strcoll_l()
函数来在新的本地化环境变量下比较两个字符串 str1
和 str2
。freelocale()
函数释放 loc
变量。注意: 在实际编程中应该特别注意本地化设置对字符处理、货币格式、时间格式等方面的影响,避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
int nftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf), int nopenfd, int flags); |
用于递归遍历指定目录下的所有文件和子目录,并对每个文件或目录执行指定操作。 |
参数:
struct stat
结构体指针,包含了当前文件的各种属性信息。FTW_F
:普通文件。FTW_D
:目录。FTW_DNR
:无法读取的目录。FTW_NS
:无法访问的文件(可能是因为权限问题)。FTW_SL
:符号链接。FTW_DP
:与 FTW_D 相同,但目录本身还未被访问。FTW_SLN
:符号链接,指向不存在的文件。struct FTW
结构体指针,包含了一些关于遍历状态的信息。FTW_CHDIR
:进入目录后更改工作目录。FTW_DEPTH
:深度优先遍历。FTW_MOUNT
:不跨越文件系统边界。FTW_PHYS
:不跟随符号链接。1 |
|
在上述的程序中,
print_file_info()
,用于打印每个文件或目录的路径和类型,并将计数器加一。nftw()
函数来递归遍历当前目录下的所有文件和子目录,并对每个文件或目录执行 print_file_info()
函数。注意: 在实际编程中应该特别注意文件访问权限等问题,以避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
int nice(int inc); |
它是一个系统调用,可将进程截止到当前用户的最大优先级减少指定的优先级,以更改进程的调度优先级。较高的 niceness 值意味着较低的优先级。 |
参数:
inc
的值为正数,则表示将进程的优先级降低;如果 inc
的值为负数,则表示将进程的优先级提高。通常情况下,只有具有 root
权限的进程才能将自己的优先级升高。1 |
|
在上述程序中,
nice(0)
函数输出当前进程的初始优先级;nice(10)
函数将进程的调度优先级降低 10
;注意: 由于
nice()
函数并不是标准C
库中的函数,因此在编译时需要传递-posix
参数或其他类似参数以启用POSIX
标准。在实际编程中应该特别注意优先级修改对进程正常运行的影响,以避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
char *nl_langinfo(nl_item item); |
它是一个 POSIX 标准函数,用于获取当前本地化环境下的语言环境信息。它可以返回一些与语言、货币、日期和时间格式等相关的信息。 |
参数:
ABDAY_*
:星期缩写名称(0 ~ 6 表示周日到周六)。DAY_*
:星期全称(0 ~ 6 表示周日到周六)。ABMON_*
:月份缩写名称(0 ~ 11 表示一月到十二月)。MON_*
:月份全称(0 ~ 11 表示一月到十二月)。AM_STR
:上午字符串。PM_STR
:下午字符串。D_FMT
:日期格式字符串。T_FMT
:时间格式字符串。ERA
:纪元字符串。ERA_D_T_FMT
:带日期和时间的纪元字符串。ERA_D_FMT
:仅带日期的纪元字符串。ERA_T_FMT
:仅带时间的纪元字符串。ALT_DIGITS
:非十进制数字字符。1 |
|
在上述的程序中,
nl_langinfo(T_FMT)
函数获取当前本地化环境下的时间格式字符串,并将其输出到终端。nl_langinfo(D_FMT)
函数获取当前本地化环境下的日期格式字符串,并将其输出到终端。注意: 在实际编程中应该特别注意处理不同本地化环境下信息的差异,以避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
long nrand48(unsigned short xsubi[3]); |
用于生成带有指定状态的随机数。它使用 48 位整数来表示随机数的状态,可以方便地切换不同的随机数生成器状态。 |
参数:
3
个 16
位无符号整数的数组,表示了当前随机数生成器的状态。如果想更改随机数生成器的状态,只需修改 xsubi
数组即可。1 |
|
在上述的程序中,
3
个 16
位无符号整数的数组 seed
,并将其用作随机数生成器的种子。srand48()
函数初始化随机数生成器,并使用 nrand48()
函数生成一个随机数,并将其输出到终端。注意: 由于
nrand48()
函数生成的是伪随机数,因此在实际使用时需要注意选择足够复杂的种子,并采取适当的加密措施以避免出现不必要的安全问题。
函数声明 | 函数功能 |
---|---|
uint32_t ntohl(uint32_t netlong); |
用于将网络字节序(大端序)转换为主机字节序(小端序)。 |
uint16_t ntohs(uint16_t netshort); |
用于将网络字节序(大端序)转换为主机字节序(小端序)。 |
参数:
32
位整数。16
位整数。1 |
|
注意: 在实际编程中应该特别注意不同平台之间的字节序差异,以避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
int mkdirat(int dirfd, const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于在指定目录下创建新的子目录 |
int mkfifo(const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于创建命名管道 |
int mkstemp(char *template); |
用于在磁盘上创建一个唯一的临时文件并打开它以进行读写 |
int mkdir(const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于创建新目录 |
int mkdir(const char *pathname); |
它是在 Windows 系统下的系统调用函数,用于创建新目录 |
time_t mktime(struct tm *timeptr); |
用于将表示时间的结构体(struct tm)转换为对应的 Unix 时间戳 |
int mlock(const void *addr, size_t len); |
它是一个 Linux 系统下的系统调用函数,用于将指定内存区域锁定在物理内存中,防止其被交换到磁盘上 |
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); |
它是一个 Linux 系统下的系统调用函数,可以将一个文件或者设备映射到内存中,并返回指向该内存区域的指针 |
double modf(double x, double *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(double) |
float modff(float value, float *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(float) |
long double modfl(long double value, long double *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(long double) |
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); |
用于将文件系统挂载到指定的挂载点,并返回挂载点的文件描述符 |
int msync(void *addr, size_t length, int flags); |
用于将指定内存区域的数据同步到文件中 |
int munmap(void *addr, size_t length); |
用于取消内存映射区域,并释放与之相关的资源 |
int munlock(const void *addr, size_t len); |
用于将之前使用mlock()函数锁定的内存区域解锁,使其可被操作系统交换出去或被回收 |
函数声明 | 函数功能 |
---|---|
int mkdirat(int dirfd, const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于在指定目录下创建新的子目录 |
参数:
AT_FDCWD
,则表示使用当前工作目录返回值:
0
;-1
,并设置错误码(errno
)。1 |
|
在上述的示例代码中,
/tmp
目录并获取其文件描述符 dirfd
;mkdirat()
函数,并将目录的文件描述符、要创建的新目录的名称和路径以及目录的权限模式作为参数传递给函数。如果函数调用成功,则新目录将在 /tmp
目录下创建。close()
函数关闭文件。注意:
mkdirat()
函数时,我们需要确保指定的父目录存在并具有适当的权限。函数声明 | 函数功能 |
---|---|
int mkfifo(const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于创建命名管道 |
参数:
返回值:
0
;-1
,并设置错误码(errno
)。1 |
|
注意:
mkfifo()
函数时,我们需要确保指定的路径可被访问并且不存在同名的文件或目录。函数声明 | 函数功能 |
---|---|
int mkstemp(char *template); |
用于在磁盘上创建一个唯一的临时文件并打开它以进行读写 |
参数:
6
个连续 'X'
的字符串的指针,这些 'X'
将被替换为随机字符以创建唯一的文件名。例如,"/tmp/tempfile-XXXXXX"
将会被替换为类似 "/tmp/tempfile-5ZqYU2"
的唯一文件名。1 |
|
如上演示了,在 windows
下 创建临时文件:
temp_file_template
,它包含连续的 6
个 'X'
;mkstemp()
函数,并将指向 temp_file_template
的指针作为参数传递给函数。如果函数调用成功,则返回新创建文件的文件描述符,并将 temp_file_template
中的 'X'
替换为随机字符以形成唯一的文件名;printf()
函数,输出该临时文件的名称;close()
函数关闭临时文件。0
表示程序执行成功。注意: 在使用
mkstemp()
函数时,我们需要确保提供的模板字符串至少包含6
个'X'
,并且文件命名方式不能与现有文件冲突。
函数声明 | 函数功能 |
---|---|
int mkdir(const char *pathname, mode_t mode); |
它是一个 Linux 系统下的系统调用函数,用于创建新目录 |
int mkdir(const char *pathname); |
它是在 Windows 系统下的系统调用函数,用于创建新目录 |
参数:
返回值:
0
;-1
,并设置错误码(errno
)。1 |
|
1 |
|
Windows 下示例运行结果
函数声明 | 函数功能 |
---|---|
time_t mktime(struct tm *timeptr); |
用于将表示时间的结构体(struct tm)转换为对应的 Unix 时间戳 |
参数:
struct tm
结构体的指针,其中包含要转换为 Unix
时间戳的日期和时间信息返回值:
Unix
时间戳;-1
。1 |
|
在上面的示例代码中,
struct tm
结构体 my_time
,并将其初始化为 0
;1900
,月份应该从 0
开始计数减去 1
;mktime()
函数,并将指向 my_time
结构体的指针作为参数传递给函数。如果函数调用成功,则返回对应于输入时间的 Unix
时间戳。Unix
时间戳。注意:
mktime()
函数时,我们需要确保提供的 struct tm
结构体中的所有字段都已正确设置。mktime()
函数所使用的时区可能与系统默认的时区不同,所以在某些情况下,转换结果可能会有一定偏差。函数声明 | 函数功能 |
---|---|
int mlock(const void *addr, size_t len); |
它是一个 Linux 系统下的系统调用函数,用于将指定内存区域锁定在物理内存中,防止其被交换到磁盘上 |
参数:
返回值:
0
;-1
,并设置错误码(errno
)。1 |
|
在上述的示例代码中,
malloc()
函数分配了一个页大小的内存区域,并使用 memset()
函数将其清零;mlock()
函数,并将指向分配内存区域起始地址的指针以及内存区域的长度作为参数传递给函数。如果函数调用成功,则锁定分配的内存区域,防止其被交换到磁盘上;strncpy()
函数向上述的分配内存区域中写入字符串 "Hello world!"
,并通过 printf()
函数输出该字符串】;munlock()
函数解除内存区域的锁定;注意: 在使用
mlock()
函数时,我们需要确保指定的内存区域已正确分配并且足够大,以避免锁定错误的内存区域。
函数声明 | 函数功能 |
---|---|
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); |
它是一个 Linux 系统下的系统调用函数,可以将一个文件或者设备映射到内存中,并返回指向该内存区域的指针 |
参数:
NULL
,由内核选定PROT_NONE
: 区域不能被访问。PROT_READ
: 区域可被读取。PROT_WRITE
: 区域可被写入。PROT_EXEC
: 区域可被执行。MAP_SHARED
: 允许多个进程共享该映射区域,对映射区域所做的修改将反映到所有共享该区域的进程中。MAP_PRIVATE
: 该映射区域只允许当前进程进行访问,对映射区域所做的修改不会反映到其他进程中。MAP_FIXED
: 强制将映射区域放置在指定的地址处(如果该地址已经被占用,则会导致错误)。MAP_ANONYMOUS
: 创建一个匿名映射区域,不与任何文件关联。MAP_FILE
: 将映射区域与文件关联,需要指定文件描述符和偏移量。MAP_LOCKED
: 指示内核在物理存储器中锁定映射区域的页面,以确保在访问该区域时不会发生缺页中断。1 |
|
上述的示例代码,演示了如何使用 mmap()
函数将一个文件映射到内存中,并使用指针 ptr
访问这个映射区域 :
open()
函数打开文件 "example.txt"
,并检查是否成功打开。mmap()
函数将文件的前 4096
字节映射到内存中,同时指定保护方式为可读写(PROT_READ | PROT_WRITE
)以及共享属性(MAP_SHARED
)。strncpy()
函数向映射区域中写入字符串 "Hello world!"
,并通过 printf()
函数输出该字符串。munmap()
函数取消映射,并关闭文件。函数声明 | 函数功能 |
---|---|
double modf(double x, double *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(double) |
float modff(float value, float *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(float) |
long double modfl(long double value, long double *iptr); |
用于将浮点数 value 拆分为其整数部分和小数部分(long double) |
参数:
value
的整数部分1 |
|
函数声明 | 函数功能 |
---|---|
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); |
用于将文件系统挂载到指定的挂载点,并返回挂载点的文件描述符 |
参数:
NULL
(表示根据 filesystemtype
参数自动选择默认源)1 |
|
在上面的示例代码中,我们调用 mount()
函数将 /dev/sda1
设备文件上的 ext4
文件系统挂载到 /mnt/usbdrive
目录下,并检查挂载操作是否成功。如果 mount()
函数返回值为 -1
,则表示挂载失败,通过 perror()
函数输出错误信息并返回 1
,程序异常结束;否则,打印 “File system mounted successfully!”
表示挂载成功,并返回 0
,程序正常结束。
函数声明 | 函数功能 |
---|---|
int msync(void *addr, size_t length, int flags); |
用于将指定内存区域的数据同步到文件中 |
参数:
cache
内容无效1 |
|
在上面的示例代码中,
open()
函数打开文件 "example.txt"
;mmap()
函数将文件的前 4096
字节映射到内存中;strncpy()
函数向映射区域中写入新的数据,并通过 msync()
函数将修改后的数据同步回磁盘文件;munmap()
函数解除映射并关闭文件。函数声明 | 函数功能 |
---|---|
int munmap(void *addr, size_t length); |
用于取消内存映射区域,并释放与之相关的资源 |
参数:
在调用 munmap()
函数后,操作系统将取消指定的内存映射,并回收相应的资源,包括虚拟地址空间和关联的物理内存页(如果存在)。此外,取消映射还可能导致未同步到磁盘文件中的修改数据丢失。
注意: 必须在对映射区域进行任何修改或者访问之前,先使用
mmap()
函数将文件映射到内存中;并在完成所有操作之后,再使用munmap()
函数解除映射。否则,可能会引发各种错误或者异常情况。
参见 7.2 的 演示示例,这里不再赘述
函数声明 | 函数功能 |
---|---|
int munlock(const void *addr, size_t len); |
用于将之前使用mlock()函数锁定的内存区域解锁,使其可被操作系统交换出去或被回收 |
参数:
返回值:
0
;-1
,并设置错误码(errno
)。注意: 只有拥有相应权限的进程才能解锁该内存区域。
参见 6.2 的 演示示例,这里不再赘述
函数声明 | 函数功能 |
---|---|
void *malloc(size_t size); |
用于动态分配内存 |
int mblen(const char *s, size_t n); |
检查多字节字符的长度 |
size_t mbrlen(const char *s, size_t n, mbstate_t *ps); |
检查多字节字符的长度 |
size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps); |
将多字节字符转换为宽字符 |
int mbsinit(const mbstate_t *ps); |
检查转换状态是否为起始状态 |
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); |
用于将多字节字符序列转换为宽字符序列。 |
size_t mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps); |
用于将多字节字符序列转换为宽字符序列,并在转换过程中自动更新 mbstate_t 转换状态结构体。 |
int mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n); |
用于将一个多字节字符 (Multibyte Character) 转换成一个宽字符 (Wide Character)。 |
void *memccpy(void *restrict dst, const void *restrict src, int c, size_t n); |
用于将内存块的内容复制到另一个内存块中,并在指定字符出现时停止复制。 |
void *memchr(const void *s, int c, size_t n); |
用于在某一内存块中查找指定字符的位置。 |
void *memcpy(void *dest, const void *src, size_t n); |
用于将源内存块中的 n 个字节复制到目标内存块中。 |
int memcmp(const void *s1, const void *s2, size_t n); |
用于比较两个内存块的内容是否相同。 |
void *memmove(void *dest, const void *src, size_t n); |
用于将源内存块中的 n 个字节复制到目标内存块中。与 memcpy() 函数不同的是,memmove() 函数在复制过程中会处理内存块重叠的情况。 |
void *memset(void *s, int c, size_t n); |
用于将一个内存块中的所有字节都设置为指定的值。 |
errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); |
C11 标准新增了一个名为 memset_s() 的安全版本函数。与 memset() 函数不同的是,memset_s() 函数会在设置内存块值时检查目标内存块大小,并防止缓冲区溢出、重叠等安全问题。 |
函数声明 | 函数功能 |
---|---|
void *malloc(size_t size); |
用于动态分配内存 |
参数:
返回值:
1 |
|
在上面的示例程序中,
str
,并将其初始化为 NULL
;malloc()
函数动态分配了 20 字节的内存空间,并将其赋值给 str
指针;strcpy()
函数将字符串 "Hello, world!"
复制到内存中,并使用 printf()
函数输出字符串;free()
函数释放了分配的内存空间。函数声明 | 函数功能 |
---|---|
int mblen(const char *s, size_t n); |
检查多字节字符的长度 |
参数:
注意: 如果 s
是空指针,则返回 0,表示不是多字节字符;否则,如果 n
不足以包含完整的多字节字符,则返回 -1,表示需要更多的输入;否则,返回多字节字符所需的字节数。
1 |
|
在上面的示例程序中,
setlocale()
函数设置本地化环境,以便正确处理多字节字符。str
;mblen()
函数检查第一个字符的长度,并将其保存到变量 len
中。函数声明 | 函数功能 |
---|---|
size_t mbrlen(const char *s, size_t n, mbstate_t *ps); |
检查多字节字符的长度 |
参数:
mbstate_t
结构体的指针注意: 如果 s
是空指针,则返回 0,表示不是多字节字符;否则,如果 n
不足以包含完整的多字节字符,则返回 (size_t)-2
,表示需要更多的输入;否则,如果 ps
是 NULL
,则使用默认转换状态;否则,将 ps
的值更新为已经转换的字符数,并返回多字节字符所需的字节数。
1 |
|
在上面的示例程序中,
setlocale()
函数设置本地化环境,以便正确处理多字节字符。str
;mbrlen()
函数检查第一个字符的长度,并将其保存到变量 len
中。函数声明 | 函数功能 |
---|---|
size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps); |
将多字节字符转换为宽字符 |
参数:
返回值:
(size_t)-1
。1 |
|
在上面的示例程序中,
setlocale()
函数设置本地化环境,以便正确处理多字节字符。str
;mbrtowc()
函数将第一个字符转换为宽字符,并将其保存到变量 wc
中。wprintf()
函数输出宽字符。注意: 在调用
mbrtowc()
函数之前,必须将mbstate_t
结构体的值初始化为0
。在 C99 标准中,可以使用大括号对结构体进行初始化,这会把结构体或数组的每个元素都初始化为默认值(0
或NULL
)。
函数声明 | 函数功能 |
---|---|
int mbsinit(const mbstate_t *ps); |
检查转换状态是否为起始状态 |
参数: |
mbstate_t
结构体的指针,表示要检查的转换状态。注意: 如果
ps
是空指针,则返回非零值(真),表示默认转换状态已经初始化;否则,如果ps
描述的转换状态是起始状态,则返回非零值(真);否则,返回0
(假)。
1 |
|
在上面的示例程序中,
str
和一个转换状态结构体 state
;mbsinit()
函数检查转换状态是否为起始状态;"The conversion state is initial."
。函数声明 | 函数功能 |
---|---|
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); |
用于将多字节字符序列转换为宽字符序列。 |
参数: |
返回值:
\0
;(size_t)-1
。1 |
|
在上面的示例程序中,我们首先定义了一个包含中文字符的字符串 str
和一个用于存储结果宽字符序列的缓冲区 wcbuf
。然后我们使用 mbstowcs()
函数将多字节字符序列转换为宽字符序列,并在控制台输出相应的信息。
注意: 在计算缓冲区大小时,必须将其指定为宽字符数(即
sizeof(wcbuf)/sizeof(wchar_t)
),而不是字节数或字符数。这是因为在Windows
等一些操作系统中,wchar_t
类型并不总是占用固定的字节数,而可能会根据编译器和平台而变化。
函数声明 | 函数功能 |
---|---|
size_t mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps); |
用于将多字节字符序列转换为宽字符序列,并在转换过程中自动更新 mbstate_t 转换状态结构体。 |
参数:
返回值:
\0
;(size_t)-1
。注意:
mbsrtowcs()
函数会自动更新转换状态结构体mbstate_t
,以记录上一次调用的状态并在下一次调用时继续使用。这使得mbsrtowcs()
函数适用于处理长的、包含部分多字节字符的字符串。它会自动识别和处理多字节字符序列中的部分字符,并等待更多的字节,直到可以完成转换为止。
1 |
|
函数声明 | 函数功能 |
---|---|
int mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n); |
用于将一个多字节字符 (Multibyte Character) 转换成一个宽字符 (Wide Character)。 |
参数:
返回值:
-1
;0
。1 |
|
函数声明 | 函数功能 |
---|---|
void *memccpy(void *restrict dst, const void *restrict src, int c, size_t n); |
用于将内存块的内容复制到另一个内存块中,并在指定字符出现时停止复制。 |
参数: |
返回值:
n
个字节中包含字符 c
,则返回指向字符 c
后面一个字节的指针;NULL
。1 |
|
函数声明 | 函数功能 |
---|---|
void *memchr(const void *s, int c, size_t n); |
用于在某一内存块中查找指定字符的位置。 |
参数:
n
个字节中查找指定字符1 |
|
在上述程序中,
str
和要查找的指定字符 ch
;memchr()
函数查找字符串 str
中是否包含指定字符 ch
;函数声明 | 函数功能 |
---|---|
void *memcpy(void *dest, const void *src, size_t n); |
用于将源内存块中的 n 个字节复制到目标内存块中。 |
参数:
1 |
|
注意: 在使用
memcpy()
函数进行内存复制时,目标内存块必须足够大,以容纳源内存块中的全部内容。否则,复制过程可能会导致访问非法内存空间,从而导致代码异常或崩溃。因此,在进行内存复制时,应该尽量避免超出目标内存块大小的范围。
函数声明 | 函数功能 |
---|---|
int memcmp(const void *s1, const void *s2, size_t n); |
用于比较两个内存块的内容是否相同。 |
参数:
注意: memcmp()
函数会逐一比较两个内存块中对应位置上的字节大小,直到找到差异或者比较完全部字节。
0
;s1
中该字节的值减去 s2
中该字节的值)。1 |
|
注意: 在比较两个内存块时,应该确保被比较的内存块中包含足够的字节,并且待比较的字节数不超过内存块大小,否则函数可能会出现异常行为。另外,由于返回值是有符号整数类型,因此在比较时应该将其强制转换为无符号整数类型,以避免出现不必要的错误。
函数声明 | 函数功能 |
---|---|
void *memmove(void *dest, const void *src, size_t n); |
用于将源内存块中的 n 个字节复制到目标内存块中。与 memcpy() 函数不同的是,memmove() 函数在复制过程中会处理内存块重叠的情况。 |
参数:
注意: memmove()
函数会将源内存块中的前 n
个字节复制到目标内存块中,并返回指向目标内存块起始地址的指针。
1 |
|
注意: 在使用 memmove()
函数进行内存复制时,目标内存块必须足够大,以容纳源内存块中的全部内容。否则,复制过程可能会导致访问非法内存空间,从而导致代码异常或崩溃。此外,由于 memmove()
函数的处理开销较大,因此在不涉及内存块重叠时,应该尽量使用 memcpy()
函数以提高效率。
函数声明 | 函数功能 |
---|---|
void *memset(void *s, int c, size_t n); |
用于将一个内存块中的所有字节都设置为指定的值。 |
errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); |
C11 标准新增了一个名为 memset_s() 的安全版本函数。与 memset() 函数不同的是,memset_s() 函数会在设置内存块值时检查目标内存块大小,并防止缓冲区溢出、重叠等安全问题。 |
memset 参数:
memset_s 参数:
1 |
|
函数声明 | 函数功能 |
---|---|
void list_add(struct list_head *new, struct list_head *head); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将新节点添加到双向链表的头部 |
void list_add_tail(struct list_head *new, struct list_head *head); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将新节点添加到链表尾部。 |
void list_cut_before(struct list_head *new, struct list_head *head, struct list_head *entry); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将一段节点从原始链表中移动到另一个链表中,并将其添加到新链表的头部。 |
void list_cut_position(struct list_head *new, struct list_head *head, struct list_head *entry); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将一段节点从原始链表中移动到另一个链表中,并将其添加到新链表的头部。与list_cut_before不同的是,该函数需要指定要移动的节点的具体位置,而不是直接指定一个节点。 |
void list_del(struct list_head *entry); |
用于从链表中删除一个节点,但不会修改该节点的指针信息。 |
void list_del_init(struct list_head *entry); |
用于从链表中删除一个节点,但会将被删除的节点的指针信息初始化为NULL。 |
void list_del_init_careful(struct list_head *entry, struct list_head *prev, struct list_head *next); |
用于从链表中删除一个节点,但需要指定该节点的前驱节点和后继节点,以确保链表结构正确。 |
int list_empty(const struct list_head *head); |
用于判断链表是否为空,并返回非零值表示为空,返回0表示不为空 |
int list_empty_careful(const struct list_head *head); |
用于判断链表是否为空,但会先检查链表头部的指针是否为空,以避免对空指针进行解引用。 |
void list_move(struct list_head *list, struct list_head *head); |
用于将一个节点移动到另外一个链表的头部。 |
void list_move_tail(struct list_head *list, struct list_head *head); |
用于将一个节点移动到另外一个链表的尾部。 |
void list_bulk_move_tail(struct list_head *list, int count, struct list_head *head); |
用于将多个节点从一个链表移动到另一个链表的尾部。 |
void list_replace(struct list_head *old, struct list_head *new); |
用于用一个新节点替换指定节点。 |
void list_replace_init(struct list_head *old, struct list_head *new); |
除了可以完成 list_replace 做的所有操作外,它还将原来的节点初始化为空。 |
static inline void list_rotate_left(struct list_head *head) |
用于将链表向左旋转一个位置。 |
void list_rotate_to_front(struct list_head *head, struct list_head *pivot); |
用于将指定节点移到链表头部,并旋转链表使得该节点成为新的头部。 |
void list_splice(struct list_head *list, struct list_head *head); |
用于将一个链表中的所有节点插入到另一个链表的指定位置之前。 |
void list_splice_tail(struct list_head *list, struct list_head *head); |
用于将一个链表中的所有节点插入到另一个链表的尾部。 |
void list_splice_init(struct list_head *list, struct list_head *head); |
除了可以完成 list_splice 做的所有操作外,它还将原来的链表初始化为空。 |
void list_splice_tail_init(struct list_head *list, struct list_head *head); |
除了可以完成 list_splice_tail 做的所有操作外,它还将原来的链表初始化为空。 |
void list_swap(struct list_head *list1, struct list_head *list2); |
交换两个链表头部的位置。 |
函数声明 | 函数功能 |
---|---|
void list_add(struct list_head *new, struct list_head *head); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将新节点添加到双向链表的头部 |
void list_add_tail(struct list_head *new, struct list_head *head); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将新节点添加到链表尾部。 |
参数: |
list_add()
函数会将 new 节点插入到链表头之前,使其成为新的链表头节点。list_add_tail()
函数会根据 链表头节点找到链表尾节点,并将 new 节点添加到链表尾部。1 |
|
在上述示例代码中,我们首先定义了 list_head
和 node
两个结构体,并通过调用 init_list_head()
函数初始化链表头部。然后,我们创建了三个 node
类型的节点,前两个节点分别通过 list_add()
函数将它们添加到链表的头部,最后一个节点通过 list_add_tail()
函数添加到链表的尾部 。最后,我们调用 print_list()
函数打印链表中的元素。
注意: 在使用
list_add()
和list_add_tail()
函数之前,我们要为每个新节点分配内存空间。
函数声明 | 函数功能 |
---|---|
void list_cut_before(struct list_head *new, struct list_head *head, struct list_head *entry); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将一段节点从原始链表中移动到另一个链表中,并将其添加到新链表的头部。 |
void list_cut_position(struct list_head *new, struct list_head *head, struct list_head *entry); |
它是 Linux 内核中双向链表操作的一个基本函数,用于将一段节点从原始链表中移动到另一个链表中,并将其添加到新链表的头部。与list_cut_before不同的是,该函数需要指定要移动的节点的具体位置,而不是直接指定一个节点。 |
参数:
list_cut_before()
函数会将 entry 节点及其前面的所有节点从原始链表中移动到 new 所指示的链表中,并将 entry 所在位置的前一个节点作为新链表的头节点。list_cut_position()
函数会将 entry 节点及其后面的所有节点从原始链表中移动到 new 所指示的链表中,并将 entry 所在位置作为新链表的头节点。
1 |
|
在上述示例代码中,我们首先定义了 list_head
和 node
两个结构体,并通过调用 init_list_head()
函数初始化两个链表的头部。然后,我们创建了三个 node
类型的节点并分别将它们添加到第一个链表的尾部。接着,我们利用list_cut_before()
函数和 list_cut_position()
函数将链表中的一段节点移动到第二个链表中。最后,我们调用 print_list
函数分别打印两个链表中的元素。
函数声明 | 函数功能 |
---|---|
void list_del(struct list_head *entry); |
用于从链表中删除一个节点,但不会修改该节点的指针信息。 |
void list_del_init(struct list_head *entry); |
用于从链表中删除一个节点,但会将被删除的节点的指针信息初始化为NULL。 |
void list_del_init_careful(struct list_head *entry, struct list_head *prev, struct list_head *next); |
用于从链表中删除一个节点,但需要指定该节点的前驱节点和后继节点,以确保链表结构正确。 |
参数:
1 |
|
在上述示例代码中,我们首先定义了 list_head
和 node
两个结构体,并通过调用 init_list_head()
函数初始化链表头部。然后,我们创建了三个 node
类型的节点并分别将它们添加到链表的尾部。接下来,我们利用 list_del()
、 list_del_init()
和 list_del_init_careful()
函数从链表中删除节点,并打印每次操作后的链表元素。
注意: 在使用这些函数之前,我们要确保被删除的节点在链表中。
函数声明 | 函数功能 |
---|---|
int list_empty(const struct list_head *head); |
用于判断链表是否为空,并返回非零值表示为空,返回0表示不为空 |
int list_empty_careful(const struct list_head *head); |
用于判断链表是否为空,但会先检查链表头部的指针是否为空,以避免对空指针进行解引用。 |
参数:
1 |
|
在上述示例代码中,我们首先定义了 list_head
和 node
两个结构体,并通过调用init_list_head()函数初始化链表头部。然后,我们利用list_empty()和list_empty_careful()函数分别判断链表是否为空,并打印其返回值。接下来,我们创建了两个node类型的节点并分别将它们添加到链表的尾部。每次添加节点后,我们再次使用list_empty和list_empty_careful函数判断链表是否为空,并打印其返回值。
需要注意的是,在使用这些函数之前,我们要确保链表头部已经初始化。
宏定义 | 宏描述 |
---|---|
#define list_entry(ptr, type, member) ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) |
用于获取一个节点所在结构体的起始地址。 |
static inline int list_entry_is_head(const struct list_head *entry, const struct list_head *head) { return entry->prev == head; } |
用于判断给定节点是否为链表头。 |
#define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member) |
用于获取链表中第一个节点所在结构体的起始地址。 |
#define list_first_entry_or_null(ptr, type, member) ({ struct list_head *__head = (ptr); struct list_head *__pos = __head->next; __pos != __head ? list_entry(__pos, type, member) : NULL; }) |
用于获取链表中第一个节点所在结构体的起始地址,但会先检查链表是否为空,以避免对空指针进行解引用。 |
#define list_next_entry(pos, member) list_entry((pos)->member.next, typeof(*(pos)), member) |
用于获取链表中紧随给定节点之后的节点所在结构体的起始地址。 |
#define list_last_entry(ptr, type, member) list_entry((ptr)->prev, type, member) |
用于获取链表中最后一个节点所在结构体的起始地址。 |
#define list_prepare_entry(pos, ptr, member) ((pos) ? : list_entry(ptr, typeof(*pos), member)) |
用于准备一个节点的数据结构指针。如果该指针为NULL,则将其初始化为链表的头部。 |
#define list_prev_entry(pos, member) list_entry((pos)->member.prev, typeof(*(pos)), member) |
用于获取链表中紧靠给定节点之前的节点所在结构体的起始地址。 |
#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next) |
遍历链表中的所有节点 |
#define list_for_each_continue(pos, head) for (pos = pos->next; pos != (head); pos = pos->next) |
从当前节点继续遍历链表中的剩余节点。 |
#define list_for_each_prev(pos, head) for (pos = (head)->prev; pos != (head); pos = pos->prev) |
从链表尾部开始遍历所有节点。 |
#define list_for_each_safe(pos, n, head) for (pos = (head)->next, n = pos->next; pos != (head); pos = n, n = pos->next) |
与list_for_each函数类似,但允许在遍历过程中删除或添加节点。其中,n参数表示要处理的下一个节点。 |
#define list_for_each_prev_safe(pos, n, head) for (pos = (head)->prev, n = pos->prev; pos != (head); pos = n, n = pos->prev) |
与list_for_each_safe函数类似,但遍历顺序是从链表尾部开始。 |
#define list_for_each_entry(pos, head, member) for (pos = list_first_entry(head, typeof(*pos), member); &pos->member != (head); pos = list_next_entry(pos, member)) |
用于在遍历链表时,获取每个节点所在结构体的起始地址。其中,pos参数表示当前节点所在结构体的指针;head参数表示要遍历的链表头部指针;member参数表示每个节点在结构体中的成员名称。 |
#define list_for_each_entry_reverse(pos, head, member) for (pos = list_last_entry(head, typeof(*pos), member); &pos->member != (head); pos = list_prev_entry(pos, member)) |
与list_for_each_entry函数类似,但遍历顺序是从链表尾部开始。 |
#define list_for_each_entry_continue(pos, head, member) for (pos = list_next_entry(pos, member); &pos->member != (head); pos = list_next_entry(pos, member)) |
用于从当前节点继续往后遍历链表,并获取每个节点所在结构体的起始地址。 |
#define list_for_each_entry_continue_reverse(pos, head, member) for (pos = list_prev_entry(pos, member); &pos->member != (head); pos = list_prev_entry(pos, member)) |
与list_for_each_entry_continue函数类似,但遍历顺序是从链表尾部开始。 |
#define list_for_each_entry_from(pos, head, member) for (; &pos->member != (head); pos = list_next_entry(pos, member)) |
用于从某个节点开始遍历链表,并获取每个节点所在结构体的起始地址。其中,pos参数表示当前要遍历的节点所在结构体的指针;head参数表示要遍历的链表头部指针;member参数表示每个节点在结构体中的成员名称。 |
#define list_for_each_entry_from_reverse(pos, head, member) for (; &pos->member != (head); pos = list_prev_entry(pos, member)) |
与list_for_each_entry_from函数类似,但遍历顺序是从链表尾部开始。 |
#define list_for_each_entry_safe(pos, n, head, member) for (pos = list_first_entry(head, typeof(*pos), member), n = list_next_entry(pos, member); &pos->member != (head); pos = n, n = list_next_entry(n, member)) |
与list_for_each_entry函数类似,但允许在遍历过程中删除或添加节点。其中,n参数表示要处理的下一个节点。 |
#define list_for_each_entry_safe_continue(pos, n, head, member) for (pos = list_next_entry(pos, member), n = list_next_entry(pos, member); &pos->member != (head); pos = n, n = list_next_entry(n, member)) |
用于从当前节点继续往后遍历链表,并允许在遍历过程中删除或添加节点。 |
#define list_for_each_entry_safe_from(pos, n, head, member) for (n = list_next_entry(pos, member); &pos->member != (head); pos = n, n = list_next_entry(n, member)) |
用于从某个节点开始遍历链表,并允许在遍历过程中删除或添加节点。 |
#define list_for_each_entry_safe_reverse(pos, n, head, member) for (pos = list_last_entry(head, typeof(*pos), member), n = list_prev_entry(pos, member); &pos->member != (head); pos = n, n = list_prev_entry(n, member)) |
与list_for_each_entry_reverse函数类似,但允许在遍历过程中删除或添加节点。 |
#define list_is_first(pos, head) ((pos)->prev == (head)) |
用于检查当前节点是否为链表中的第一个节点。其中,pos 参数表示要检查的节点指针;head 参数表示链表头部指针。 |
#define list_is_last(pos, head) ((pos)->next == (head)) |
用于检查当前节点是否为链表中的最后一个节点。其中,pos 参数表示要检查的节点指针;head 参数表示链表头部指针。 |
#define list_is_head(pos, head) ((pos) == (head)) |
用于检查当前节点是否为链表头部。其中,pos参数表示要检查的节点指针;head参数表示链表头部指针。 |
#define list_is_singular(head) (!list_empty(head) && ((head)->next == (head)->prev)) |
用于检查链表中是否只有一个节点。其中,head参数表示链表头部指针。 |
#define list_safe_reset_next(curr, next, member) next = list_entry((curr)->member.next, typeof(*curr), member) |
用于安全地重置一个节点的后继节点指针,以便在遍历链表时删除当前节点。其中,curr 参数表示当前节点指针;next 参数表示当前节点的后继节点指针;member 参数表示节点结构体中 struct list_head 成员的名称。 |
函数声明 | 函数功能 |
---|---|
void list_move(struct list_head *list, struct list_head *head); |
用于将一个节点移动到另外一个链表的头部。 |
void list_move_tail(struct list_head *list, struct list_head *head); |
用于将一个节点移动到另外一个链表的尾部。 |
void list_bulk_move_tail(struct list_head *list, int count, struct list_head *head); |
用于将多个节点从一个链表移动到另一个链表的尾部。 |
参数:
1 |
|
上述示例代码中,我们首先创建了两个链表 a
和 b
,然后向链表 a
中添加三个结构体。接着,我们使用 list_move()
函数将节点 s1
从链表 a
移动到链表 b
的头部,使用 list_move_tail()
函数将节点 s2
从链表 a
移动到链表 b
的尾部,最后使用 list_bulk_move_tail()
函数将链表 a
中的所有节点都移动到链表 b
的尾部。
注意: 在上述演示代码的最后,我们需要手动释放所有节点的内存空间,以免造成内存泄漏。
函数声明 | 函数功能 |
---|---|
void list_replace(struct list_head *old, struct list_head *new); |
用于用一个新节点替换指定节点。 |
void list_replace_init(struct list_head *old, struct list_head *new); |
除了可以完成 list_replace 做的所有操作外,它还将原来的节点初始化为空。 |
参数:
1 |
|
在上面的示例代码中,我们首先创建了一个链表 a
,然后向其中添加三个结构体。接着,我们使用 list_replace()
函数将第二个节点 s2
替换成新节点 s4
,并打印出替换后的链表元素;然后,我们使用 list_replace_init()
函数将第一个节点 s1
替换成新节点 s4
,并清空原来的节点,同样打印出替换后的链表元素。
函数声明 | 函数功能 |
---|---|
static inline void list_rotate_left(struct list_head *head) |
用于将链表向左旋转一个位置。 |
void list_rotate_to_front(struct list_head *head, struct list_head *pivot); |
用于将指定节点移到链表头部,并旋转链表使得该节点成为新的头部。 |
参数:
1 |
|
在上面的示例代码中,我们首先创建了一个链表 a
,然后向其中添加三个结构体。接着,我们使用 list_rotate_to_front()
函数将第二个节点 s2
移到链表头部并旋转链表,打印出操作后的链表元素;然后,我们使用 list_rotate_left()
函数将链表向左旋转一个位置,同样打印出操作后的链表元素。
函数声明 | 函数功能 |
---|---|
void list_splice(struct list_head *list, struct list_head *head); |
用于将一个链表中的所有节点插入到另一个链表的指定位置之前。 |
void list_splice_tail(struct list_head *list, struct list_head *head); |
用于将一个链表中的所有节点插入到另一个链表的尾部。 |
void list_splice_init(struct list_head *list, struct list_head *head); |
除了可以完成 list_splice 做的所有操作外,它还将原来的链表初始化为空。 |
void list_splice_tail_init(struct list_head *list, struct list_head *head); |
除了可以完成 list_splice_tail 做的所有操作外,它还将原来的链表初始化为空。 |
参数: |
list_splice()
和 list_splice_init()
中表示目标链表插入的位置list_splice_tail()
和 list_splice_tail_init()
中表示目标链表尾部的前一个节点1 |
|
上述演示代码中,我们创建了两个链表 a
和 b
,并初始化为空。然后,我们向链表 a
中添加三个结构体,向链表 b 中添加两个结构体,并使用 list_for_each_entry
宏分别遍历两个链表并输出节点数据。
接着,我们使用 list_splice()
函数将链表 b
中的所有节点插入到链表 a
的头部,使用 list_splice_tail()
函数将链表 b
中的所有节点插入到链表 a
的尾部,并使用 list_for_each_entry
宏再次遍历两个链表并输出节点数据,可以看到链表 a
中包含了链表 b
中的所有节点。
接下来,我们使用 INIT_LIST_HEAD
宏重新初始化链表 a
并使用 list_splice_init()
函数将链表 b
中的所有节点插入到链表 a
的头部,使用 INIT_LIST_HEAD
宏重新初始化链表 b
并使用 list_splice_tail_init()
函数将链表 a
中的所有节点插入到链表 b
的尾部,并使用 list_for_each_entry
宏再次遍历两个链表并输出节点数据,可以看到两个链表中的节点顺序已经被重新排列。
函数声明 | 函数功能 |
---|---|
void list_swap(struct list_head *list1, struct list_head *list2); |
交换两个链表头部的位置。 |
参数: | |
list1 和 list2 分别指向两个要交换头部的链表。 |
1 |
|
在上述示例中,我们创建了两个链表 a
和 b
,并向链表 a
中添加三个节点,向链表 b
中添加一个节点。然后我们使用 list_for_each_entry
宏遍历两个链表并输出节点数据。
接着,我们使用 list_swap()
函数交换链表 a
和链表 b
的头部,并使用 list_for_each_entry
宏再次遍历两个链表并输出节点数据,可以看到链表 a
的头部变成了原来的链表 b
的头部,链表 b
的头部变成了原来的链表 a
的头部。
函数声明 | 函数功能 |
---|---|
long labs(long n); |
计算长整型的绝对值 |
long long int llabs(long long int n); |
计算long long int 类型整数的绝对值 |
double ldexp(double x, int exp); |
计算 x 乘以 2 的指定次幂(double) |
float ldexpf(float x, int exp); |
计算 x 乘以 2 的指定次幂(float) |
long double ldexpl(long double x, int exp); |
计算 x 乘以 2 的指定次幂(long double) |
ldiv_t ldiv(long int numer, long int denom); |
计算两个 long int 类型整数的商和余数 |
lldiv_t lldiv(long long int numer, long long int denom); |
计算两个 long long int 类型整数的商和余数 |
void *lfind(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); |
它是标准 C 库函数 <search.h> 中的一个函数,用于在一个数组中查找指定元素。 |
void line( int x1, int y1, int x2, int y2); |
在指定两点间画一直线 |
void linerel(int dx, int dy); |
从当前位置绘制一条指定长度和方向的线段。 |
void lineto(int x, int y); |
从当前位置绘制一条直线到指定位置 |
struct tm *localtime(const time_t *timep); |
将 UNIX 时间戳转换为本地时间 |
int lock(int fd, int cmd, off_t len); |
它是标准 C 库函数 <fcntl.h> 中的一个函数,用于对文件进行加锁或解锁操作 |
double log(double x); |
计算自然对数 |
double log10(double x); |
计算以 10 为底的对数 |
void longjmp(jmp_buf env, int val); |
跳转到指定的程序位置并恢复相应的上下文环境 |
void lowvideo(void); |
用于将文本颜色设置为低对比度模式 |
unsigned long _lrotl(unsigned long value, int shift); |
它是 Windows 系统特有的函数,用于将 32 位无符号整数按位循环左移。 |
void *lsearch(const void *key, void *base, size_t *nelp, size_t width, int (*compar)(const void *, const void *)); |
用于在指定的数组中查找指定元素,并返回该元素在数组中的地址 |
long lseek(int handle, long offset, int fromwhere); |
设置文件操作指针,即改变文件读取或写入的位置 |
char *ltoa(long value, char *str, int radix); |
用于将长整型数值转换为字符串格式 |
char *lltoa(long long value, char *str, int radix); |
用于将长长整型数值转换为字符串格式 |
函数声明 | 函数功能 |
---|---|
long labs(long n); |
计算长整型的绝对值 |
long long int llabs(long long int n); |
计算long long int 类型整数的绝对值 |
1 |
|
函数声明 | 函数功能 |
---|---|
double ldexp(double x, int exp); |
计算 x 乘以 2 的指定次幂(double) |
float ldexpf(float x, int exp); |
计算 x 乘以 2 的指定次幂(float) |
long double ldexpl(long double x, int exp); |
计算 x 乘以 2 的指定次幂(long double) |
1 |
|
注意:ldexp,ldexpf,ldexpl 函数会对参数进行溢出和下溢处理,因此可以处理很大或很小的数值。
函数声明 | 函数功能 |
---|---|
ldiv_t ldiv(long int numer, long int denom); |
计算两个 long int 类型整数的商和余数 |
lldiv_t lldiv(long long int numer, long long int denom); |
计算两个 long long int 类型整数的商和余数 |
参数:
ldiv
函数的返回值类型 ldiv_t
是一个结构体类型,定义如下:
1 | typedef struct { |
lldiv
函数的返回值类型 lldiv_t
是一个结构体类型,定义如下:
1 | typedef struct { |
1 |
|
注意: 如果 denom 参数为零,则
ldiv()
函数会产生一个异常情况。此外,如果两个参数中有一个或两个都是负数,则商和余数的计算规则将根据 C 标准进行调整。
函数声明 | 函数功能 |
---|---|
void *lfind(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); |
它是标准 C 库函数 <search.h> 中的一个函数,用于在一个数组中查找指定元素。 |
参数:
1 |
|
注意:
lfind()
函数使用线性搜索算法,因此对于大规模数据可能不太适用。除此之外,该函数还有一些变种函数,例如bsearch()
和tfind()
等,也可以用于在数组或树结构中查找元素。
函数声明 | 函数功能 |
---|---|
void line( int x1, int y1, int x2, int y2); |
在指定两点间画一直线 |
参数: |
(x1, y1) : 第一个点的坐标
(x2, y3) : 第二个点的坐标
1 |
|
函数声明 | 函数功能 |
---|---|
void linerel(int dx, int dy); |
从当前位置绘制一条指定长度和方向的线段。 |
参数: |
1 |
|
函数声明 | 函数功能 |
---|---|
void lineto(int x, int y); |
从当前位置绘制一条直线到指定位置 |
参数: |
x : 线段终点的 X 坐标
y : 线段终点的 Y 坐标
1 |
|
函数声明 | 函数功能 |
---|---|
struct tm *localtime(const time_t *timep); |
将 UNIX 时间戳转换为本地时间 |
参数: |
返回值:
1 |
|
注意: 在使用
localtime()
函数时需要注意结构体中的字段值是否正确,例如月份、星期等的表示方式可能因不同系统而异。
函数声明 | 函数功能 |
---|---|
int lock(int fd, int cmd, off_t len); |
它是标准 C 库函数 <fcntl.h> 中的一个函数,用于对文件进行加锁或解锁操作 |
参数: |
返回值:
返回一个整数值表示操作是否成功,若成功则返回 0,否则返回 -1
1 |
|
上述示例程序中,首先通过 open()
函数打开一个名为 test.txt
的文件,并设置文件访问模式为可读写。接着,调用 lock()
函数对该文件进行加锁操作,保护写入数据的过程。然后,通过 write()
函数将数据写入到文件中。最后,调用 lock()
函数对该文件进行解锁操作,释放锁定的资源。
注意: 在使用
lock()
函数时需要注意加锁和解锁的顺序、范围等问题,否则可能会造成死锁或其他问题。此外,该函数只适用于文件系统,不能用于套接字等其他类型的文件描述符。
函数声明 | 函数功能 |
---|---|
double log(double x); |
计算自然对数 |
参数: |
返回值:
ln(x)
。1 |
|
注意: 由于
log()
函数接受的参数和返回值都是double
类型,因此在使用时需要保证传入的参数类型正确,避免发生精度损失等问题。同时,log()
函数的参数不能为负数或零,否则会产生不可预知的行为。
函数声明 | 函数功能 |
---|---|
double log10(double x); |
计算以 10 为底的对数 |
参数: |
返回值:
log10(x)
1 |
|
函数声明 | 函数功能 |
---|---|
void longjmp(jmp_buf env, int val); |
跳转到指定的程序位置并恢复相应的上下文环境 |
参数: |
注意:在使用
longjmp()
函数之前,需要先调用setjmp()
函数来设置上下文环境,并将其保存在jmp_buf
数据类型中。然后,在程序执行过程中,如果需要跳转到之前设定的位置,就可以使用longjmp()
函数进行跳转和上下文恢复。
1 |
|
上述示例程序中,首先在主函数中调用 setjmp()
函数设置上下文环境,并将其保存在 buf 变量中。然后,程序调用 do_something()
函数,在其中调用 longjmp()
函数跳转到之前设定的位置,并返回值为 1。
由于 longjmp()
调用后不会返回到调用它的位置,因此 do_something()
函数在被调用后并未执行完毕,而是直接跳转到了 setjmp()
所在的位置。当程序回到 setjmp()
处时,检测到了从 longjmp()
跳转过来的信号,并返回值为 1,表示跳转成功。
最后,程序输出 "Program ends with value 1."
,结束运行。
注意: 使用
longjmp()
和setjmp()
函数进行跳转时,必须保证跳转的目标位置和之前设置的上下文环境是兼容的,否则可能会导致程序崩溃或其他严重问题。同时,尽管longjmp()
可以快速跳出当前函数或代码块,但在实际应用中应该尽量避免使用它,以免造成代码逻辑混乱和难以调试的问题。
函数声明 | 函数功能 |
---|---|
void lowvideo(void); |
用于将文本颜色设置为低对比度模式 |
1 |
|
当该程序运行时,首先清空了控制台屏幕,然后将文本颜色设置为高对比度模式并输出一段文本。接着,将文本颜色设置为低对比度模式,并将光标移动到第二行第一个字符位置,输出另外一段文本。最后,程序执行结束,并返回 0。
注意:
<conio.h>
头文件中的函数在不同的操作系统和编译器下可能会有所不同,并且并非所有的平台都支持低对比度文本模式。在实际应用中,应该避免过度使用低对比度模式,以免影响用户体验和可读性。
函数声明 | 函数功能 |
---|---|
unsigned long _lrotl(unsigned long value, int shift); |
它是 Windows 系统特有的函数,用于将 32 位无符号整数按位循环左移。 |
参数: |
返回值:
1 |
|
注意:
_lrotl()
函数是 Windows 系统特有的函数,在其他操作系统或编译器下可能不可用或使用方式有所不同。此外,由于该函数只适用于 32 位无符号整数,如果需要对 64 位整数进行位移操作,则需要使用其他函数。
函数声明 | 函数功能 |
---|---|
void *lsearch(const void *key, void *base, size_t *nelp, size_t width, int (*compar)(const void *, const void *)); |
用于在指定的数组中查找指定元素,并返回该元素在数组中的地址 |
参数: |
1 |
|
上述示例程序中,首先定义了一个整型数组 arr 并初始化为 { 3, 1, 4, 1, 5, 9, 2, 6, 5 }
。然后,将要查找的元素值 key 设置为 5,并调用 lsearch()
函数在数组中查找该元素。如果找到了,则输出该元素在数组中的下标;否则输出未找到的提示。
注意:
lsearch()
函数在查找数组元素时,只能够找到第一个匹配的元素,并返回其地址。如果数组中存在多个相同的元素,则无法区分它们的位置。此外,使用lsearch()
函数进行查找时,必须保证数组已经按照指定的比较函数从小到大排好序,否则可能会导致查找失败或找到错误的元素。
函数声明 | 函数功能 |
---|---|
long lseek(int handle, long offset, int fromwhere); |
设置文件操作指针,即改变文件读取或写入的位置 |
参数: |
- SEEK_SET: 从文件开头开始计算偏移量(即绝对位置)
- SEEK_CUR: 从当前位置开始计算偏移量(即相对位置)
- SEEK_END: 从文件结尾开始计算偏移量(即反向偏移)
返回值:
- 如果发生错误,则返回 -1。
1 |
|
上述示例程序中,首先使用 open()
函数打开名为 "temp.txt"
的文件,并获取其文件描述符。然后,调用 lseek()
函数将文件指针移动到距离文件开头 5 个字节处。接着,调用 read()
函数从该位置开始读取 5 个字节的数据,并输出读取结果。
注意:
lseek()
函数只能够对可寻址的文件进行操作,如磁盘文件、终端设备等,而不能对无法随机访问的流式数据进行操作,如管道、套接字等。同时,在使用lseek()
函数时应该注意文件操作模式和文件共享模式,以免影响其他进程或线程的文件访问。
函数声明 | 函数功能 |
---|---|
char *ltoa(long value, char *str, int radix); |
用于将长整型数值转换为字符串格式 |
参数: |
返回值:
1 |
|
注意:
ltoa()
函数在将长整型数值转换为字符串时,会将负数转换为相应的带符号字符串。如果要对无符号长整型进行转换,则需要使用其他函数或技巧。此外,由于ltoa()
函数没有对输出缓冲区溢出进行检查,因此在使用时应该确保缓冲区足够大,以免发生错误。
函数声明 | 函数功能 |
---|---|
char *lltoa(long long value, char *str, int radix); |
用于将长长整型数值转换为字符串格式 |
参数: |
返回值:
1 |
|