C语言函数大全--r 开头的函数

总览

函数声明 函数功能
int raise(int sig); 用于向当前进程发送指定的信号。
int rand(void); 用于生成伪随机数
ssize_t read(int fd, void *buf, size_t count); 用于从文件描述符读取数据的函数。
void *realloc(void *ptr, size_t size); 用于重新分配已经分配过内存的空间大小。
void rectangle( int left, int top, int right, int bottom); 画一个矩形
int registerbgidriver(void(*driver)(void)); 用于将BGI(Borland Graphics Interface)驱动程序注册到系统中
int remove(char *filename); 用于删除指定的文件
int rename(char *oldname, char *newname); 用于重命名或移动文件。
void restorecrtmode(void); 将图形模式恢复到文本模式
void rewind(FILE *stream); 将文件指针 stream 指向的文件位置重置为文件开头,同时清除任何错误或文件结束标志。
int rmdir(const char *path); 用于删除一个空目录,即该目录必须为空。
double round(double x); 将传入的实数参数 x 四舍五入为最接近的整数(double)
float roundf(float x); 将传入的实数参数 x 四舍五入为最接近的整数(float)
long double roundl(long double x); 将传入的实数参数 x 四舍五入为最接近的整数(long double)
double remainder(double x, double y); 用于计算两个浮点数的余数(即模运算结果)(double)
float remainderf (float x, float y ); 用于计算两个浮点数的余数(即模运算结果)(float)
long double remainderl (long double x, long double y); 用于计算两个浮点数的余数(即模运算结果)(long double)
double remquo(double x, double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
float remquof(float x, float y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
long double remquol(long double x, long double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
double rint(double x); 将 x 四舍五入到最接近的整数(double)
float rintf(float x); 将 x 四舍五入到最接近的整数(float)
long double rintl(long double x); 将 x 四舍五入到最接近的整数(long double)

1. raise

1.1 函数说明

函数声明 函数功能
int raise(int sig); 用于向当前进程发送指定的信号。

参数:

  • sig : 指定要发送的信号编号

返回值:

  • 如果调用成功,raise() 函数将返回 0
  • 否则,它将返回一个非零值。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void sigint_handler(int sig) {
printf("Caught signal %d\n", sig);
exit(0);
}

int main() {
signal(SIGINT, sigint_handler);

while (1) {
printf("Doing something...\n");
getchar();
// check for interrupt signal
raise(SIGINT);
}

return 0;
}

在上面的示例中,

  • 我们首先使用 signal() 函数设置了一个处理 SIGINT 信号的处理程序 sigint_handler()
  • 然后,在主循环中,我们随意输入一个字符后,就使用 raise() 函数向当前正在运行的进程发送 SIGINT 信号。当收到 SIGINT 信号时,程序将打印一条消息并退出。

注意: raise() 函数只能向当前进程发送信号,不能向其他进程发送信号。如果要向其他进程发送信号,可以使用 kill() 函数。

1.3 运行结果

2. rand

2.1 函数说明

函数声明 函数功能
int rand(void); 用于生成伪随机数

返回值:
每次调用它时会返回一个介于 0RAND_MAX 之间的伪随机整数。其中,RAND_MAX 是一个常量,表示返回值的最大值,通常为 32767

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
// 使用系统时间作为随机数种子初始化
srand(time(NULL));

// 生成并输出 10 个随机数
for (int i = 0; i < 10; i++) {
printf("%d\n", rand());
}

return 0;
}

注意:

  • 每次程序运行时,rand() 函数返回的随机数序列都是相同的。如果要生成不同的随机数序列,可以使用 srand() 函数提供的种子来初始化随机数发生器。
  • 由于 rand() 函数只能生成伪随机数,不能保证其真正的随机性。因此,在需要高度安全性的应用程序中,建议使用更加安全的随机数生成器,如 /dev/random/dev/urandom 等系统提供的硬件随机数生成器。

2.3 运行结果

3. read

3.1 函数说明

函数声明 函数功能
ssize_t read(int fd, void *buf, size_t count); 用于从文件描述符读取数据的函数。

参数:

  • fd : 要读取的文件描述符
  • buf : 存储读取数据的缓冲区
  • count : 要读取的字节数。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

int main() {
char buffer[BUFFER_SIZE];
ssize_t num_read;

num_read = read(STDIN_FILENO, buffer, BUFFER_SIZE);
if (num_read == -1) {
perror("read");
return 1;
}

printf("Read %ld bytes from standard input: %.*s", num_read, (int)num_read, buffer);

return 0;
}

在上述的示例中,

  • 我们首先定义了一个大小为 BUFFER_SIZE 的字符数组 buffer
  • 然后使用 read() 函数读取标准输入【STDIN_FILENO 表示标准输入的文件描述符】中的数据到 buffer 中;
  • 最后将读取的结果输出到控制台上。

3.3 运行结果

4. realloc

4.1 函数说明

函数声明 函数功能
void *realloc(void *ptr, size_t size); 用于重新分配已经分配过内存的空间大小。

参数:

  • ptr : 指向已分配内存区域的指针
  • size : 需要分配的新内存大小

返回值:

  • 它会尝试重新调整已经分配给 ptr 指向的内存区域大小,并返回一个指向新内存起始地址的指针。
  • 如果无法分配新的内存,则返回空指针 NULL

注意: realloc() 函数并不保证原有的内存区域内容会被完全保留。当内存大小增加时,可能会分配新的内存并将原有的数据复制到新内存区域中;当内存大小减小时,则可能截断部分原有的数据。因此,在使用 realloc() 函数时,需要注意备份原有的数据,以免出现数据丢失的情况。

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>

int main() {
// 分配 10 个整型变量的内存空间
int *p = (int*) malloc(10 * sizeof(int));
if (p == NULL) {
printf("内存分配失败\n");
exit(1);
}

// 更改为 20 个整型变量的内存空间
int *q = (int*) realloc(p, 20 * sizeof(int));
if (q == NULL) {
printf("内存分配失败\n");
exit(1);
}

// 输出新的内存地址
printf("原内存地址:%p,新内存地址:%p\n", p, q);

// 释放新分配的内存空间
free(q);

return 0;
}

在上面的示例中,

  • 我们首先使用 malloc() 函数分配了 10 个整型变量的内存空间,并判断是否分配成功。
  • 接着,我们使用 realloc() 函数将分配的内存空间大小扩充为 20 个整型变量,并判断是否分配成功。
  • 最后,我们输出了原有的内存地址和新的内存地址,并释放了新分配的内存空间。

注意: 在使用 realloc() 函数时,应该始终检查返回值,以确保分配内存空间成功,避免因内存不足或其他原因导致程序崩溃。另外,也应该避免过度使用 realloc() 函数,因为频繁地重新分配内存会影响程序性能。

5. rectangle

5.1 函数说明

函数声明 函数功能
void rectangle( int left, int top, int right, int bottom); 画一个矩形

参数:
left, top, right, bottom,它们分别表示矩形左上角和右下角的坐标。

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode;
int left, top, right, bottom;

initgraph(&gdriver, &gmode, "");

left = getmaxx() / 2 - 50;
top = getmaxy() / 2 - 50;
right = getmaxx() / 2 + 50;
bottom = getmaxy() / 2 + 50;

rectangle(left,top,right,bottom);

getch();
closegraph();
return 0;
}

5.3 运行结果

6. registerbgidriver

6.1 函数说明

函数声明 函数功能
int registerbgidriver(void(*driver)(void)); 用于将BGI(Borland Graphics Interface)驱动程序注册到系统中

注意:
它必须在使用任何 BGI 图形函数之前调用。该函数接受一个指向驱动程序结构的指针作为参数,并返回一个整数值以指示是否成功注册了驱动程序。BGI 驱动程序主要用于支持 Borland C++IDE 环境下的图形绘制和显示操作,它们通常存储在一个单独的库文件中,例如 graphics.h 头文件需要使用的 BGI driver 位于 libbgi.a 文件中。

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");
registerbgidriver(EGAVGA_driver); // 注册EGAVGA驱动程序
circle(100, 100, 50); // 绘制圆形
getch(); // 等待用户输入
closegraph(); // 关闭图形界面
return 0;
}

7. remove

7.1 函数说明

函数声明 函数功能
int remove(char *filename); 用于删除指定的文件

参数:

  • filename : 一个指向要删除文件的文件名的字符串指针

返回值:
返回一个整数表示操作是否成功

  • 如果文件成功删除,则返回 0
  • 否则,返回非零值以指示发生错误。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main()
{
int result;
char filename[] = "example.txt";
result = remove(filename);
if (result == 0)
{
printf("The file %s has been removed.\n", filename);
}
else
{
printf("Error deleting the file %s.\n", filename);
}
return 0;
}

7.3 运行结果


8. rename

8.1 函数说明

函数声明 函数功能
int rename(char *oldname, char *newname); 用于重命名或移动文件。

参数:

  • oldname : 指定要更改的文件名
  • newname : 指定新文件名或包含新路径的新文件名

返回值:

  • 在执行成功时,该函数返回 0
  • 否则返回非零值以指示发生错误。

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>

int main()
{
char oldname[] = "temp.txt";
char newname[] = "tempnew.txt";
int result;

result = rename(oldname, newname);

if (result == 0)
{
printf("The file has been renamed.\n");
}
else
{
printf("Error renaming the file.\n");
}

return 0;
}

8.3 运行结果

9. restorecrtmode

9.1 函数说明

函数声明 函数功能
void restorecrtmode(void); 将图形模式恢复到文本模式

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int gdriver = DETECT, gmode;
int x, y;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "Press any key to exit graphics:");
getch();

// 将图形模式恢复到文本模式
restorecrtmode();
printf("We're now in text mode.\n");
printf("Press any key to return to graphics mode:");
getch();

// 返回图形模式
setgraphmode(getgraphmode());

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "We're back in graphics mode.");
outtextxy(x, y+textheight("W"), "Press any key to halt:");

getch();
closegraph();
return 0;
}

9.3 运行结果

10. rewind

10.1 函数说明

函数声明 函数功能
void rewind(FILE *stream); 将文件指针 stream 指向的文件位置重置为文件开头,同时清除任何错误或文件结束标志。

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

int main() {
FILE *fp = fopen("tempnew.txt", "r");
if (fp == NULL) {
perror("Failed to open file");
return 1;
}

// 读取文件内容
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}

printf("\n");

// 将文件指针重置到开头
rewind(fp);

// 再次读取文件内容
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}

fclose(fp);
return 0;
}

在上述的示例中,

  • 我们首先打开一个名为 tempnew.txt 的文件;
  • 然后使用 fgets() 函数从文件中读取文本行,并输出内容;
  • 接着使用 rewind() 函数将文件指针重置到文件开头,并再次读取文件内容并输出;
  • 最后关闭文件,退出程序。

10.3 运行结果

11. rmdir

11.1 函数说明

函数声明 函数功能
int rmdir(const char *path); 用于删除一个空目录,即该目录必须为空。

参数:

  • path : 待删除的空目录路径

返回值:

  • 如果成功,则返回 0
  • 否则返回 -1,并设置 errno 错误码。

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *dir_name = "test";
if (mkdir(dir_name) I= 0) {
perror("Failed to create directory");
return 1;
}

//在目录中创建一些文件
FILE *fp1 = fopen("test/file1.txt","w");
FILE *fp2 = fopen("test/file2.txt","w");
fclose(fp1);
fclose(fp2);

//尝试刪除非空目录
if (rmdir(dir name) |= 0) {
perror("Failed to remove directory");
return 1;
}
printf("Directory removed successfullyIn");
return 0;
}

在上述的示例中,

  • 我们首先创建一个名为 test 的目录;
  • 然后在其中创建两个文件 file1.txtfile2.txt
  • 接着使用 rmdir() 函数尝试删除该目录,但会失败,因为该目录不是空的。

注意: 如果要删除非空目录,可以使用上面的 remove() 函数来删除目录及其所有内容。

11.3 运行结果

12. round,roundf,roundl

12.1 函数说明

函数声明 函数功能
double round(double x); 将传入的实数参数 x 四舍五入为最接近的整数(double)
float roundf(float x); 将传入的实数参数 x 四舍五入为最接近的整数(float)
long double roundl(long double x); 将传入的实数参数 x 四舍五入为最接近的整数(long double)

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <math.h>
#include <stdio.h>

int main() {
double x = 3.14159265;

double rounded1 = round(x); // 将 x 四舍五入为整数,结果为 3
double rounded2 = round(x * 100) / 100; // 将 x 精确到小数点后两位,结果为 3.14

printf("rounded1: %lf\n", rounded1);
printf("rounded2: %lf\n", rounded2);

float xf = 2.5;
printf("rountf(%f) = %f\n", xf, roundf(xf)); // 将 xf 四舍五入为整数,结果为 3

long double xL = 2.4;
printf("rountl(%Lf) = %Lf", xL, roundl(xL)); // 将 xL 四舍五入为整数,结果为 2
return 0;
}

12.3 运行结果

13. remainder,remainderf,remainderl

13.1 函数说明

函数声明 函数功能
double remainder(double x, double y); 用于计算两个浮点数的余数(即模运算结果)(double)
float remainderf (float x, float y ); 用于计算两个浮点数的余数(即模运算结果)(float)
long double remainderl (long double x, long double y); 用于计算两个浮点数的余数(即模运算结果)(long double)

参数:

  • x : 被除数
  • y : 除数

返回值: x/y 的余数

13.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>

int main() {
double x = 10.5, y = 3.2;
printf("remainder(%lf, %lf) = %.20lf\n", x, y, remainder(x, y));


float xf = 10.5f, yf = 3.2f;
printf("remainder(%f, %f) = %.20f\n", xf, yf, remainderf(xf, yf));


long double xL = 10.5L, yL = 3.2L;
printf("remainder(%Lf, %Lf) = %.20Lf\n", xL, yL, remainderl(xL, yL));
return 0;
}

13.3 运行结果

14. remquo,remquof,remquol

14.1 函数说明

函数声明 函数功能
double remquo(double x, double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
float remquof(float x, float y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
long double remquol(long double x, long double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。

参数:

  • x : 被除数
  • y : 除数
  • quo : 返回商的指针。如果不需要返回商,则可以传递 NULL

返回值: 返回 x/y 的余数,并通过 quo 指针返回商。

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>

int main() {
int quo;
double x = 10.5, y = 3.2;
double rem = remquo(x, y, &quo);
printf("remquo(%lf, %lf, quo) = %.20lf, quo = %d\n", x, y, rem, quo);

float xf = 10.5f, yf = 3.2f;
float remf = remquof(xf, yf, &quo);
printf("remquof(%f, %f, quo) = %.20f, quo = %d\n", xf, yf, remf, quo);

long double xL = 10.5L, yL = 3.2L;
long double remL = remquol(xL, yL, &quo);
printf("remquol(%Lf, %Lf, quo) = %.20Lf, quo = %d\n", xL, yL, remL, quo);

return 0;
}

14.3 运行结果

15. rint,rintf,rintl

15.1 函数说明

函数声明 函数功能
double rint(double x); 将 x 四舍五入到最接近的整数(double)
float rintf(float x); 将 x 四舍五入到最接近的整数(float)
long double rintl(long double x); 将 x 四舍五入到最接近的整数(long double)

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <math.h>

int main() {
double d = 3.7;
float f = 2.4f;
long double ld = 5.9L;

printf("rint(%f) = %.1f\n", d, rint(d)); // Output: rint(3.700000) = 4.0
printf("rintf(%f) = %.1f\n", f, rintf(f)); // Output: rintf(2.400000) = 2.0
printf("rintl(%Lf) = %.1Lf\n", ld, rintl(ld)); // Output: rintl(5.900000) = 6.0

return 0;
}

15.3 运行结果

参考

  1. [API Reference Document]

C语言函数大全--q 开头的函数

总览

函数声明 函数功能
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 用于将指定数组按指定顺序进行排序
void quick_exit(int status); 它是 C11 标准中新增的函数,用于快速退出程序并执行一些清理操作。它类似于 exit() 函数,但不会调用 atexit() 注册的函数,并且不会刷新标准 I/O 流(例如 stdoutstderr)。
int qunsetenv(const char *name); 用于从进程环境中移除指定的环境变量。该函数在某些操作系统上可能不可用,因为它并非标准的 C 语言函数,而是 POSIX 标准中定义的函数。
QuRT相关的函数 详见 4.1 所示

1. qsort

1.1 函数说明

函数声明 函数功能
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 用于将指定数组按指定顺序进行排序
参数:
  • base : 指向要排序的数组的第一个元素的指针
  • nmemb : 表示数组中元素的数量
  • size : 表示每个元素的大小(以字节为单位)
  • compar : 指向一个函数,用于比较两个元素的值。该函数需要接受两个 const void* 类型的参数,分别指向要比较的两个元素,并返回一个整数值,表示它们的相对顺序。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}

int main() {
int arr[] = { 5, 2, 8, 4, 1, 9, 3, 6, 7 };
size_t n = sizeof(arr) / sizeof(int);

printf("Before sorting:");
for (int i = 0; i < n; i++) {
printf(" %d", arr[i]);
}
printf("\n");

qsort(arr, n, sizeof(int), compare);

printf("After sorting:");
for (int i = 0; i < n; i++) {
printf(" %d", arr[i]);
}
printf("\n");

return 0;
}

在上述的示例中,

  • 我们首先定义了一个整数数组 arr,并计算出数组的长度,赋值给 n
  • 接着我们输出原始数组 "Before sorting: 5 2 8 4 1 9 3 6 7"
  • 然后我们使用 qsort() 函数将其按照升序排列。qsort() 函数中传入一个比较函数 compare(),用于比较两个元素的值。
  • 最后我们再次输出排序后的结果 ”After sorting: 1 2 3 4 5 6 7 8 9“

注意: 在编写比较函数时,需要根据元素的实际类型进行转换,并确保返回值符合要求(小于零表示第一个元素小于第二个元素,等于零表示两个元素相等,大于零表示第一个元素大于第二个元素)。此外,还需要特别注意参数类型和返回值类型的 const 限定符。

1.3 运行结果

2. quick_exit

2.1 函数说明

函数声明 函数功能
void quick_exit(int status); 它是 C11 标准中新增的函数,用于快速退出程序并执行一些清理操作。它类似于 exit() 函数,但不会调用 atexit() 注册的函数,并且不会刷新标准 I/O 流(例如 stdoutstderr)。
参数:
  • status :程序退出时返回的状态码,0 表示程序正常退出,非零值表示出现了异常情况。

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

void cleanup() {
printf("Cleaning up...\n");
}

int main() {
if (at_quick_exit(cleanup) != 0) {
fprintf(stderr, "Failed to register cleanup function\n");
exit(EXIT_FAILURE);
}

printf("Running...\n");

quick_exit(EXIT_SUCCESS);
}

在如上的示例中,

  • 我们首先使用 at_quick_exit() 函数注册一个清理函数 cleanup(),当程序使用 quick_exit() 函数退出时,该函数会自动执行。
  • 然后,我们调用 quick_exit() 函数并传入状态码 EXIT_SUCCESS 表示程序正常退出。

注意: 在使用 quick_exit() 函数时需要特别小心,因为它不会调用 atexit() 注册的函数,并且可能导致一些资源泄漏或未完成的操作。只有在必须立即结束程序并执行清理操作时,才应该使用该函数。

3. qunsetenv

3.1 函数说明

函数声明 函数功能
int qunsetenv(const char *name); 用于从进程环境中移除指定的环境变量。该函数在某些操作系统上可能不可用,因为它并非标准的 C 语言函数,而是 POSIX 标准中定义的函数。
参数:
  • name : 要移除的环境变量的名称

返回值:

  • 如果环境变量不存在,则不进行任何操作,并返回 0
  • 否则将其移除,并返回一个非零值。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdlib.h>
#include <stdio.h>

int main() {
// 设置一个环境变量
setenv("MY_VAR", "hello world", 1);

// 移除这个环境变量
if (qunsetenv("MY_VAR") != 0) {
perror("qunsetenv() failed");
exit(EXIT_FAILURE);
}

// 尝试访问这个环境变量
char *val = getenv("MY_VAR");
if (val == NULL) {
printf("Environment variable MY_VAR has been removed.\n");
} else {
printf("Unexpected value: %s\n", val);
}

return EXIT_SUCCESS;
}

在上述这个示例程序中,

  • 我们首先使用 setenv() 函数设置了一个名为 MY_VAR 的环境变量;
  • 然后使用 qunsetenv() 函数移除了这个环境变量;
  • 最后再次尝试访问这个环境变量,如果返回值为 NULL,则说明环境变量已经被成功移除了。

注意: 使用 qunsetenv() 函数可以修改当前进程的环境变量,但是对于其他进程或子进程来说,它们的环境变量不受影响。此外,一些操作系统可能不支持对环境变量进行动态修改,因此无法保证 qunsetenv() 函数在所有平台上都能正常工作。

4. QuRT

4.1 函数说明

函数声明 函数功能
void *qurt_sysenv_getvirtaddr(void *phys_addr, unsigned int size); 将物理地址转换为虚拟地址。
void *qurt_malloc(unsigned int size); 动态分配内存
void *qurt_calloc(unsigned int nmemb, unsigned int size); 动态分配内存,并初始化为零。
void qurt_free(void *ptr); 释放动态分配的内存。
int qurt_thread_create(qurt_thread_t *tid, const qurt_thread_attr_t *attr, void (*start)(void *), void *arg); 创建新线程。
int qurt_thread_join(qurt_thread_t tid, int *status); 等待线程结束并释放其资源。
unsigned int qurt_thread_get_priority(qurt_thread_t thread); 用于获取指定线程的优先级。其中参数 thread 是要获取优先级的线程的句柄。返回一个无符号整数,表示线程的优先级。
void qurt_thread_set_priority(qurt_thread_t thread, unsigned int priority); 用于设置指定线程的优先级。其中参数 thread 是要设置优先级的线程的句柄,而参数 priority 是要设置的优先级值。
char *qurt_thread_get_name(char *name, qurt_thread_t thread); 用于获取指定线程的名称。其中参数 name 是一个指向存储线程名称的缓冲区的指针,而参数 thread 是要获取名称的线程的句柄。返回一个指向缓冲区中存储线程名称的指针。
void qurt_thread_set_name(qurt_thread_t thread, const char *name); 用于设置指定线程的名称。其中参数 thread 是要设置名称的线程的句柄,而参数 name 是要设置的线程名称。
int qurt_thread_stop(qurt_thread_t thread); 用于停止指定线程的执行,即立即终止线程的运行。其中参数 thread 是要停止执行的线程的句柄。返回一个整数值,表示是否成功停止线程。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_thread_resume(qurt_thread_t thread); 用于恢复指定线程的执行,即让线程从上次暂停处继续运行。其中参数 thread 是要恢复执行的线程的句柄。返回一个整数值,表示是否成功恢复线程。如果成功,则返回 0;否则返回一个负数错误代码。
void qurt_mutex_init(qurt_mutex_t *mutex); 用于初始化一个互斥锁,即在使用之前必须进行初始化。其中参数 mutex 是指向要初始化的互斥锁对象的指针。
void qurt_mutex_lock(qurt_mutex_t *mutex); 用于以阻塞方式获取一个互斥锁。如果该互斥锁已被其他线程锁定,则当前线程将一直等待,直到可以获取该锁。其中参数 mutex 是指向要获取的互斥锁对象的指针。
void qurt_mutex_unlock(qurt_mutex_t *mutex); 用于释放一个互斥锁,即解除对该互斥锁的占用。其中参数 mutex 是指向要释放的互斥锁对象的指针。
void qurt_timer_sleep(unsigned int ticks); 用于让当前线程进入休眠状态,休眠时间由参数 ticks 指定(每个 tick 的长度取决于系统时钟频率)。在休眠期间,该线程将不会被调度执行。注意,该函数可能会提前唤醒线程,因此休眠时间并不精确。
void qurt_signal_init(qurt_signal_t *signal); 用于初始化一个信号量,即在使用之前必须进行初始化。其中参数 signal 是指向要初始化的信号量对象的指针。
unsigned int qurt_signal_wait(qurt_signal_t *signal, unsigned int mask, unsigned int option, unsigned int *ret_signal); 用于等待一个或多个信号量的触发。其中参数 signal 是指向要等待的信号量对象的指针,参数 mask 表示要等待哪些信号量,参数 option 用于指定等待的行为选项,参数 ret_signal 用于返回实际触发的信号量。
void qurt_signal_set(qurt_signal_t *signal, unsigned int mask); 用于触发一个或多个信号量。其中参数 signal 是指向要触发的信号量对象的指针,参数 mask 表示要触发哪些信号量。
void qurt_signal2_init(qurt_signal2_t *signal); 用于初始化一个带有两个信号量的信号量对象。其中参数 signal 是指向要初始化的信号量对象的指针。
void qurt_signal2_destroy(qurt_signal2_t *signal); 用于销毁带有两个信号量的信号量对象,并释放其占用的内存空间。其中参数 signal 是要销毁的信号量对象的指针。
void qurt_signal2_set(qurt_signal2_t *signal, unsigned int mask); 用于设置带有两个信号量的信号量对象中的一个或多个信号量。其中参数 signal 是要设置信号量的信号量对象的指针,而参数 mask 是一个 32 位无符号整数,表示要设置的信号量掩码。掩码中每个位代表一个信号量,如果该位为 1,则表示相应的信号量被设置;如果该位为 0,则表示相应的信号量未被设置。
unsigned int qurt_signal2_wait(qurt_signal2_t *signal, unsigned int mask, unsigned int options); 用于等待带有两个信号量的信号量对象中指定的信号量被触发。其中参数 signal 是要等待的信号量对象的指针,而参数 mask 是一个 32 位无符号整数,表示要等待的信号量掩码。掩码中每个位代表一个信号量,如果该位为 1,则表示相应的信号量需要被触发;如果该位为 0,则表示相应的信号量不需要被触发。参数 options 则指定等待信号量的选项,例如是否超时等。它返回一个 32 位无符号整数,表示哪些信号量已被触发。返回值中每个位代表一个信号量,如果该位为 1,则表示相应的信号量已被触发;如果该位为 0,则表示相应的信号量未被触发。
void qurt_timer_create(qurt_timer_t *timer, const char *name); 用于创建一个新的定时器。其中参数 timer 是指向要创建的定时器对象的指针,参数 name 是定时器的名称(可以为 NULL)。
void qurt_timer_delete(qurt_timer_t timer); 用于删除一个已经创建的定时器。其中参数 timer 是要删除的定时器对象。
void qurt_timer_start(qurt_timer_t timer, uint32_t duration); 用于启动一个定时器,并指定定时器的超时时间。其中参数 timer 是要启动的定时器对象,参数 duration 是定时器的超时时间(以 tick 为单位)。
void qurt_timer_stop(qurt_timer_t timer); 用于停止一个已经运行的定时器。其中参数 timer 是要停止的定时器对象。
qurt_thread_t qurt_thread_get_id(void); 用于获取当前线程的 ID
int qurt_mem_region_create(qurt_mem_region_t *region, unsigned int size, qurt_mem_cache_mode_t cache_attrib, qurt_mem_region_type_t type); 用于创建一个内存区域对象,并分配指定大小的内存空间。其中参数 region 是指向要创建的内存区域对象的指针,参数 size 指定内存区域的大小,而 cache_attribtype 分别指定内存区域的缓存属性和类型。返回一个整数值,表示是否成功创建内存区域。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_mem_region_delete(qurt_mem_region_t region); 用于删除指定的内存区域对象,并释放其占用的内存空间。其中参数 region 是要删除的内存区域对象的句柄。返回一个整数值,表示是否成功删除内存区域。如果成功,则返回 0;否则返回一个负数错误代码。
void qurt_mem_region_attr_init(qurt_mem_region_attr_t *attr); 用于初始化一个内存区域属性对象。其中参数 attr 是指向要初始化的内存区域属性对象的指针。
int qurt_mem_pool_create(qurt_mem_pool_t *pool, void *baseaddr, unsigned int size, qurt_mem_cache_mode_t cache_attrib); 用于创建一个内存池对象,并分配指定大小的内存空间。其中参数 pool 是指向要创建的内存池对象的指针,参数 baseaddr 指定内存池的起始地址,而 sizecache_attrib 分别指定内存池的大小和缓存属性。返回一个整数值,表示是否成功创建内存池。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_mem_pool_delete(qurt_mem_pool_t pool); 用于删除指定的内存池对象,并释放其占用的内存空间。其中参数 pool 是要删除的内存池对象的句柄。返回一个整数值,表示是否成功删除内存池。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_create(qurt_pipe_t *pipe, unsigned int pipe_type, unsigned int pipe_elements, unsigned int elem_size); 用于创建一个管道对象,并分配指定大小的内存空间。其中参数 pipe 是指向要创建的管道对象的指针,参数 pipe_type 指定管道类型,参数 pipe_elements 指定管道元素个数,而 elem_size 指定每个管道元素的大小。 返回一个整数值,表示是否成功创建管道。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_delete(qurt_pipe_t pipe); 用于删除指定的管道对象,并释放其占用的内存空间。其中参数 pipe 是要删除的管道对象的句柄。返回一个整数值,表示是否成功删除管道。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_send(qurt_pipe_t pipe_id, void *buf, unsigned int size, unsigned int timeout); 用于向指定的管道发送数据。其中参数 pipe_id 是要发送数据的管道对象的句柄,参数 buf 指向要发送的数据缓冲区,参数 size 指定要发送的数据大小,而 timeout 指定等待发送操作完成的超时时间(单位为 ticks)。 返回一个整数值,表示是否成功发送数据。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_receive(qurt_pipe_t pipe_id, void *buf, unsigned int size, unsigned int *recv_size, unsigned int timeout); 用于从指定的管道接收数据。其中参数 pipe_id 是要接收数据的管道对象的句柄,参数 buf 指向接收数据的缓冲区,参数 size 指定要接收的数据大小,而 recv_size 是一个指针,用于返回实际接收到的数据大小。参数 timeout 指定等待接收操作完成的超时时间(单位为 ticks)。返回一个整数值,表示是否成功接收数据。如果成功,则返回 0;否则返回一个负数错误代码。

4.2 演示示例

4.2.1 QuRT 创建线程示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include "qurt.h"

void task1(void *arg) {
printf("Task 1 is running...\n");
printf("Task 1 is done.\n");
}

void task2(void *arg) {
printf("Task 2 is running...\n");
printf("Task 2 is done.\n");
}

int main() {
qurt_thread_t t1, t2;
qurt_thread_attr_t attr;

qurt_thread_attr_init(&attr);
qurt_thread_create(&t1, &attr, (void (*)(void *))task1, NULL);
qurt_thread_create(&t2, &attr, (void (*)(void *))task2, NULL);

qurt_thread_join(t1, NULL);
qurt_thread_join(t2, NULL);

return 0;
}

在上述的示例中,我们使用 qurt_thread_create() 函数创建了两个线程,分别执行 task1()task2() 函数,并使用 qurt_thread_join() 函数等待它们结束。
注意: 在开发过程中,需要根据实际情况合理使用内存管理函数和多任务调度函数,并避免出现死锁、资源泄漏等问题。

4.2.2 QuRT 互斥锁示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "qurt.h"
#include <stdio.h>

// 共享资源
int global_counter = 0;

// 互斥锁对象
static qurt_mutex_t mutex;

int main() {
// 初始化互斥锁对象
qurt_mutex_init(&mutex);

// 创建两个线程,同时访问共享资源
qurt_thread_t thread1, thread2;
qurt_thread_create(&thread1, NULL, increment_global_counter, NULL);
qurt_thread_create(&thread2, NULL, increment_global_counter, NULL);

// 等待两个线程结束
qurt_thread_join(thread1, NULL);
qurt_thread_join(thread2, NULL);

// 输出最终结果
printf("Global counter: %d\n", global_counter);

return 0;
}

void increment_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 获取互斥锁
qurt_mutex_lock(&mutex);

// 访问共享资源
++global_counter;

// 释放互斥锁
qurt_mutex_unlock(&mutex);
}
}

在上面这个示例程序中,

  • 我们首先使用 qurt_mutex_init() 函数初始化了一个互斥锁对象。
  • 然后创建了两个线程,它们都会调用 increment_global_counter() 函数来增加全局计数器 global_counter 的值。由于多个线程可能同时访问该共享资源,因此在访问之前需要先获取互斥锁,以避免竞争条件的发生。在 increment_global_counter() 函数中,我们使用 qurt_mutex_lock() 函数获取互斥锁,并使用 qurt_mutex_unlock() 函数释放互斥锁。
  • 最后,我们在主函数中输出了最终的计数器值。

4.2.3 QuRT 信号量示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "qurt.h"
#include <stdio.h>

// 共享资源
int global_counter = 0;

// 信号量对象
static qurt_signal_t sem;

int main() {
// 初始化信号量对象
qurt_signal_init(&sem);

// 创建两个线程,分别增加和减少全局计数器的值
qurt_thread_t thread1, thread2;
qurt_thread_create(&thread1, NULL, increment_global_counter, NULL);
qurt_thread_create(&thread2, NULL, decrement_global_counter, NULL);

// 等待两个线程结束
qurt_thread_join(thread1, NULL);
qurt_thread_join(thread2, NULL);

// 输出最终结果
printf("Global counter: %d\n", global_counter);

return 0;
}

void increment_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 等待信号量
qurt_signal_wait(&sem, 1, QURT_SIGNAL_ATTR_WAIT_ANY, NULL);

// 访问共享资源
++global_counter;

// 触发信号量
qurt_signal_set(&sem, 1);
}
}

void decrement_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 等待信号量
qurt_signal_wait(&sem, 1, QURT_SIGNAL_ATTR_WAIT_ANY, NULL);

// 访问共享资源
--global_counter;

// 触发信号量
qurt_signal_set(&sem, 1);
}
}

在上述的示例程序中,

  • 我们首先使用 qurt_signal_init() 函数初始化了一个信号量对象。
  • 然后创建了两个线程,一个增加全局计数器的值,一个减少全局计数器的值。由于多个线程同时访问该共享资源,因此需要使用信号量进行同步。在每个线程中,我们使用 qurt_signal_wait() 函数等待信号量,当信号量触发时才能访问共享资源,并使用 qurt_signal_set() 函数释放信号量。
  • 接着 使用 qurt_thread_join() 函数等待两个线程结束;
  • 最后输出最终结果。

4.2.4 QuRT 定时器示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "qurt.h"
#include <stdio.h>

// 定时器对象
static qurt_timer_t timer;

// 定时器回调函数
void timer_callback(int arg) {
printf("Timer expired\n");
}

int main() {
// 创建定时器对象
qurt_timer_create(&timer, NULL);

// 启动定时器
qurt_timer_start(timer, 1000);

// 注册定时器回调函数
qurt_timer_set_attr(timer, QURT_TIMER_ATTR_CALLBACK_FUNCTION, (void *)timer_callback);
qurt_timer_set_attr(timer, QURT_TIMER_ATTR_CALLBACK_ARGUMENT, (void *)0);

// 等待定时器超时
while (1) {
qurt_timer_sleep(10);
}

// 停止定时器
qurt_timer_stop(timer);

// 删除定时器对象
qurt_timer_delete(timer);

return 0;
}

在上述的示例程序中,

  • 我们首先使用 qurt_timer_create() 函数创建了一个定时器。
  • 然后使用 qurt_timer_start() 函数启动了该定时器,并指定了定时器的超时时间(1000 毫秒)。
  • 接着使用 qurt_timer_set_attr() 函数注册了定时器回调函数。
  • 最后进入一个无限循环,每隔 10 毫秒调用 qurt_timer_sleep() 函数进入休眠状态,等待定时器超时。当定时器超时时,将触发定时器回调函数 timer_callback(),输出一条消息。

注意: 在程序结束时需要使用 qurt_timer_stop() 停止定时器,并使用 qurt_timer_delete() 删除定时器对象。

4.2.5 QuRT 共享内存区域示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "qurt.h"
#include <stdio.h>

#define SHM_SIZE 1024

int main() {
// 创建共享内存区域
qurt_mem_region_t shm;
qurt_mem_region_attr_t attr;
qurt_mem_region_attr_init(&attr);
qurt_mem_region_create(&shm, SHM_SIZE, QURT_MEM_CACHE_NONE, QURT_MEM_REGION_SHARED | QURT_MEM_REGION_PERM_READ | QURT_MEM_REGION_PERM_WRITE);

// 在共享内存区域中写入数据
char *buf = (char *)qurt_mem_region_get_vaddr(&shm);
sprintf(buf, "Hello, shared memory!");

// 打印从共享内存区域中读取的数据
printf("%s\n", buf);

// 删除共享内存区域
qurt_mem_region_delete(shm);

return 0;
}

在上述这个示例程序中,

  • 我们首先使用 qurt_mem_region_create() 函数创建了一个大小为 SHM_SIZE 的共享内存区域,并设置其缓存属性为 QURT_MEM_CACHE_NONE,类型为 QURT_MEM_REGION_SHARED,并且具有读写权限。
  • 然后,在共享内存区域中写入了一些数据,并使用 printf() 函数打印了从共享内存区域中读取的数据。
  • 最后,使用 qurt_mem_region_delete() 函数删除了共享内存区域。

4.2.6 QuRT 使用管道进行进程间通信的示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "qurt.h"
#include <stdio.h>

#define PIPE_SIZE 1024

int main() {
// 创建管道
qurt_pipe_t pipe;
qurt_pipe_create(&pipe, QURT_PIPE_ATTR_BLOCKING | QURT_PIPE_ATTR_PIPE_TYPE_BYTE_QUEUE, PIPE_SIZE, 1);

// 创建子进程
qurt_thread_t child;
qurt_thread_create(&child, NULL, child_thread, (void *)&pipe);

// 向管道发送数据
char msg[] = "Hello, pipe!";
qurt_pipe_send(pipe, msg, sizeof(msg), QURT_TIME_WAIT_FOREVER);

// 等待子进程结束
qurt_thread_join(child, NULL);

// 删除管道
qurt_pipe_delete(pipe);

return 0;
}

void child_thread(void *arg) {
// 从管道接收数据
char buf[PIPE_SIZE];
unsigned int recv_size;
qurt_pipe_receive(*(qurt_pipe_t *)arg, buf, PIPE_SIZE, &recv_size, QURT_TIME_WAIT_FOREVER);

// 打印从管道中接收到的数据
printf("%s\n", buf);
}

在上述示例程序中,

  • 我们首先使用 qurt_pipe_create() 函数创建一个大小为 1024 字节的管道对象,属性设置为阻塞式字节队列。
  • 然后我们使用 qurt_thread_create() 函数创建了一个名为 child 的子线程,并将管道对象传递给它。我们在 child_thread() 函数中调用了 qurt_pipe_receive() 函数来从管道接收数据,然后使用 printf() 函数打印出接收到的字符串。
  • 接着我们定义了一个字符串 msg,并使用 qurt_pipe_send() 函数向管道发送该字符串。
  • 最后我们使用 qurt_pipe_delete() 函数删除了管道对象。

C语言函数大全--p 开头的函数

总览

函数声明 函数功能
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); 用于将一个整数值以二进制形式写入到指定的文件中。

1. perror

1.1 函数说明

函数声明 函数功能
void perror(const char *s); 用于将当前错误码对应的错误信息打印到标准输出设备(通常是终端)。

参数:

  • s : 用于描述错误类型或者出错的上下文信息。它会在该信息后面追加当前错误码对应的错误信息,并且自动换行。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <errno.h>

int main() {
FILE *fp = fopen("tempfile.txt", "r");
if (fp == NULL) {
perror("Failed to open file");
printf("Error code: %d\n", errno);
}
return 0;
}

在上述的示例中,

  • 我们首先尝试打开一个不存在的文件,并通过 fopen() 函数返回的值来检查是否成功。由于该文件不存在,fopen() 函数将返回 NULL
  • 然后我们可以使用 perror() 函数来输出一个错误消息和具体的错误信息,以帮助我们找到问题所在。如果发生了错误,errno 全局变量会被设置为一个非零值,我们还可以使用它来获取具体的错误代码。

1.3 运行结果

2. pieslice

2.1 函数说明

函数声明 函数功能
void pieslice(int x, int y, int stanle, int endangle, int radius); 在图形模式下绘制并填充一个扇形(饼图切片)

参数:

  • x : 圆心的x 坐标
  • y : 圆心的y 坐标
  • startangle : 圆弧的起始角度(以度为单位)
  • endangle : 圆弧的结束角度(以度为单位)
    • radius : 圆的半径

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <graphics.h>

int main() {
int gdriver = DETECT, gmode;
int midx, midy;
int stangle = 45, endangle = 135, radius = 100;

initgraph(&gdriver, &gmode, ""); // 初始化图形窗口

midx = getmaxx() / 2;
midy = getmaxy() / 2;

setcolor(YELLOW); // 设置画笔颜色为黄色
setfillstyle(EMPTY_FILL, getmaxcolor()); // 设置填充样式。
// 绘制一个半径为100像素、起始角度为45度、结束角度为135度的圆弧
pieslice(midx, midy, stangle, endangle, radius);

getch(); // 等待用户按键
closegraph(); // 关闭图形窗口
return 0;
}

2.3 运行结果

3. pow,powf,powl

3.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)

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <math.h>

int main() {
double result = pow(2.0, 3.5);
printf("The result of pow(2.0, 3.5) is: %.20lf\n", result);

float resultf = powf(2.0f, 3.5f);
printf("The result of powf(2.0f, 3.5f) is: %.20f\n", resultf);

long double resultL = powl(2.0L, 3.5L);
printf("The result of powl(2.0L, 3.5L) is: %.20Lf\n", resultL);
return 0;
}

3.3 运行结果

4. pow10,pow10f,pow10l

4.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)

4.2 演示示例

1
2
3
4
5
6
7
8
#include <stdio.h>
#include <math.h>

int main() {
double result = pow10(-2.0);
printf("The result is: %lf\n", result);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <cmath>

int main() {
float result = std::pow10f(-2.0f);
std::cout << "10^-2 = " << result << std::endl;

long double result = std::pow10l(-2.0L);
std::cout << "10^-2 = " << result << std::endl;

return 0;
}

5. printf

5.1 函数说明

函数声明 函数功能
int printf(const char *format, ...); 它是标准 I/O 库中定义的函数,用于将格式化的数据输出到标准输出流(通常是控制台窗口)
参数:
  • format : 一个格式化字符串
  • 可变参数 : 任意数量,这些可变参数会根据格式化字符串进行格式化,并被输出到标准输出流。

返回值 :

  • 成功打印的字符数。

5.2 演示示例

1
2
3
4
5
6
7
8
#include <stdio.h>

int main() {
printf("Hello, world!\n");
char name[20] = "Huazie";
printf("My name is %s", name);
return 0;
}

5.3 运行结果

6. pthread_create,pthread_join

6.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 参数:

  • thread : 指向线程标识符的指针,用于返回新创建线程的标识符
  • attr : 指向线程属性结构体的指针,用于指定线程的属性,通常为 NULL 表示使用默认属性
  • start_routine : 指向线程函数的指针,用于指定线程的入口点
  • arg : 传递给线程函数的参数,可以为任意类型的指针。

pthread_join 参数:

  • pthread_t thread :目标线程的标识符(由 pthread_create() 返回)。必须是已创建且未被分离(non-detached)的线程。
  • void **retval :用于接收目标线程的退出状态值的指针的地址。
    • 若目标线程通过 return 返回值或调用 pthread_exit(void *retval) 终止,retval 将指向该值。
    • 若不需要获取退出状态,可设为 NULL
    • 若目标线程被取消,retval 会被设为 PTHREAD_CANCELED(通常为 -1)。

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <pthread.h>

void *thread_func(void *arg) {
printf("Hello from the new thread!\n");
return NULL;
}

int main() {
pthread_t thread;
int ret = pthread_create(&thread, NULL, thread_func, NULL);
if (ret != 0) {
printf("Failed to create thread!\n");
return -1;
}

pthread_join(thread, NULL);

printf("Hello from the main thread!\n");
return 0;
}

在上述的示例中,主线程调用了 pthread_create() 函数来创建一个新的线程,并传递一个函数指针 thread_func 作为新线程的入口点。新线程运行这个函数,并输出一条消息。主线程等待新线程结束,然后继续运行自己的代码。

6.3 运行结果

7. pthread_mutex_init,pthread_mutex_destroy,pthread_mutex_lock,pthread_mutex_unlock

7.1 函数说明

函数声明 函数功能
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); 释放互斥锁。

参数:

  • mutex : 指向互斥锁对象的指针。
  • attr : 指向线程属性结构体的指针,用于指定互斥锁对象的属性,通常为 NULL 表示使用默认属性。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <stdio.h>
#include <pthread.h>

pthread_mutex_t mutex;

void *thread_func(void *arg) {
printf("Thread %d: Attempting to lock the mutex.\n", (int)arg);

pthread_mutex_lock(&mutex);

printf("Thread %d: Locked the mutex!\n", (int)arg);
// ... Critical section code ...
printf("Thread %d: Unlocking the mutex.\n", (int)arg);

pthread_mutex_unlock(&mutex);

return NULL;
}

int main() {
pthread_t thread1, thread2;
int ret;

ret = pthread_mutex_init(&mutex, NULL);
if (ret != 0) {
printf("Failed to initialize mutex!\n");
return -1;
}

ret = pthread_create(&thread1, NULL, thread_func, (void *)1);
if (ret != 0) {
printf("Failed to create thread 1!\n");
return -1;
}

ret = pthread_create(&thread2, NULL, thread_func, (void *)2);
if (ret != 0) {
printf("Failed to create thread 2!\n");
return -1;
}

pthread_join(thread1, NULL);
pthread_join(thread2, NULL);

pthread_mutex_destroy(&mutex);

return 0;
}

在上述的示例中,两个线程分别调用了 pthread_mutex_lock()pthread_mutex_unlock() 函数来保护临界区代码,以确保同时只有一个。

7.3 运行结果

8. putc

8.1 函数说明

函数声明 函数功能
int putc(int c, FILE *stream); 它是标准 I/O 库中定义的函数,用于将一个字符输出到指定的文件流。

参数:

  • c : 要输出的字符
  • stream : 指向目标文件流的指针

返回值:

  • 成功输出的字符的 ASCII 码

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

int main() {
FILE *fp;
char *str = "Hello, world!\n";

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("Failed to open file for writing!\n");
return -1;
}

int i = 0;
while (str[i] != '\0') {
putc(str[i], fp);
i++;
}

fclose(fp);

return 0;
}

在上述的示例中,我们打开名为 output.txt 的文件以供写入,并使用 putc() 函数将字符串中的每个字符逐一输出到文件中。最后,我们关闭文件。

注意:putchar() 函数类似,putc() 函数可以用来逐一输出字符串中的每个字符,但通常会更多地用于将数据写入文件或其他输出流。

8.3 运行结果

9. putchar

9.1 函数说明

函数声明 函数功能
int putchar(int c); 它是标准 I/O 库中定义的函数,用于将一个字符输出到标准输出流(通常是控制台窗口)。

参数:

  • c : 要输出的字符

返回值 :

  • 成功输出,则返回该字符的 ASCII 码值

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main() {
putchar('H');
putchar('e');
putchar('l');
putchar('l');
putchar('o');
putchar(',');
putchar(' ');
putchar('w');
putchar('o');
putchar('r');
putchar('l');
putchar('d');
putchar('!');
putchar('\n');
return 0;
}

注意: 单引号用于表示字符常量,例如 ‘H’ 表示字符 H 的 ASCII 码。

9.3 运行结果

10. putenv

10.1 函数说明

函数声明 函数功能
int putenv(char *string); 用于设置环境变量的值。

参数:

  • string : 字符串参数,格式为 name=value,其中 name 是要设置的环境变量的名称,value 是要为其设置的值。

返回值:

  • 0 表示成功;
  • 0 表示失败。

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>

int main() {
char *var = "MY_VAR=hello";
int ret = putenv(var);
if (ret != 0) {
printf("Failed to set environment variable!\n");
return -1;
}

char *val = getenv("MY_VAR");
printf("The value of MY_VAR is: %s\n", val);

return 0;
}

在上述的示例中,

  • 我们首先使用 putenv() 函数将一个名为 MY_VAR 的环境变量设置为字符串 "hello"
  • 然后,我们使用 getenv() 函数获取 MY_VAR 环境变量的值;
  • 最后使用 printf() 函数输出它。

注意: 由于 putenv() 函数接受一个指向可变字符串的指针,因此应该避免将局部变量的地址传递给它,以免在函数返回后出现未定义行为。

10.3 运行结果

11. putimage

11.1 函数说明

函数声明 函数功能
void putimage(int left, int top, void *bitmap, int op); 用于将位图图像输出到指定的窗口或屏幕上

参数:

  • left: 表示位图左上角的 x 坐标
  • top: 表示位图左上角的 y 坐标
  • bitmap: 一个指向位图数据的指针,这个数据必须按照指定格式存储
  • op: 表示绘制位图的方式,可以为以下值之一:
    • COPY_PUT:覆盖模式,即将位图完全覆盖到目标位置。
    • AND_PUT:按位与模式,即将位图与目标位置进行按位与运算后输出。
    • OR_PUT:按位或模式,即将位图与目标位置进行按位或运算后输出。
    • XOR_PUT:按位异或模式,即将位图与目标位置进行按位异或运算后输出。

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <graphics.h>

#define ARROW_SIZE 10

void draw_arrow(int x, int y);

int main(void)
{
int gdriver = DETECT, gmode;
void *arrow;
int x, y, maxx;
unsigned int size;

initgraph(&gdriver, &gmode, "");

maxx = getmaxx();
x = 0;
y = getmaxy() / 2;

draw_arrow(x, y);

size = imagesize(x, y-ARROW_SIZE, x+(4*ARROW_SIZE), y+ARROW_SIZE);

arrow = malloc(size);

getimage(x, y-ARROW_SIZE, x+(4*ARROW_SIZE), y+ARROW_SIZE, arrow);

while (!kbhit())
{
putimage(x, y-ARROW_SIZE, arrow, XOR_PUT);

x += ARROW_SIZE;
if (x >= maxx)
x = 0;

putimage(x, y-ARROW_SIZE, arrow, XOR_PUT);
}

free(arrow);
closegraph();
return 0;
}

void draw_arrow(int x, int y)
{
moveto(x, y);
linerel(4*ARROW_SIZE, 0);
linerel(-2*ARROW_SIZE, -1*ARROW_SIZE);
linerel(0, 2*ARROW_SIZE);
linerel(2*ARROW_SIZE, -1*ARROW_SIZE);
}

上述程序使用了 graphics.h 图形库来画一个箭头,并在屏幕上循环移动它。

  • 首先,程序初始化图形库,然后调用 getmaxx()getmaxy() 函数获取屏幕的宽度和高度。
  • 接着,程序调用 draw_arrow() 函数来绘制箭头图形,并使用 imagesize() 函数计算出需要分配给位图数据的内存大小。
  • 接下来,程序使用 malloc() 函数动态分配了一块内存空间,并调用 getimage() 函数获取箭头图像的位图数据。该函数会将指定位置的屏幕区域保存到指定的内存地址中。
  • 最后,程序进入一个循环,在每次迭代中先使用 putimage() 函数将之前存储的箭头图像覆盖掉屏幕上的箭头,然后将箭头向右移动一定的距离。当用户按下任意键时,程序结束循环并退出。

11.3 运行结果

12. putpixel

12.1 函数说明

函数声明 函数功能
void putpixel(int x, int y, int color); 用于将一个像素点画在指定的位置上

参数:

  • x: 表示要绘制像素的 x 坐标
  • y: 表示要绘制像素的 y 坐标
  • color: 表示要绘制的像素颜色,通常为一个整数值。

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <graphics.h>
#include <time.h>

#define PIXEL_COUNT 1000
#define DELAY_TIME 100

int main(void)
{
int gdriver = DETECT, gmode;
int i, x, y, color, maxx, maxy, maxcolor, seed;

initgraph(&gdriver, &gmode, "");

maxx = getmaxx() + 1;
maxy = getmaxy() + 1;
maxcolor = getmaxcolor() + 1;

while (!kbhit())
{
srand((unsigned)time(NULL));
for (i=0; i<PIXEL_COUNT; i++)
{
x = rand() % maxx + 1;
y = rand() % maxy + 1;
color = rand() % maxcolor + 1;
putpixel(x, y, color);
}

delay(DELAY_TIME);
}

getch();
closegraph();
return 0;
}

上述这个程序使用 graphics.h 图形库在屏幕上绘制随机像素点,并不断更新它们的颜色。

  • 首先,程序初始化图形库,并调用 getmaxx()getmaxy()getmaxcolor() 函数获取屏幕的尺寸和颜色范围。
  • 接着,程序进入一个循环,在每次迭代中使用 rand() 函数生成随机的坐标和颜色值,并使用 putpixel() 函数绘制对应位置的像素点。另外还使用了 delay() 函数来控制每次更新之间的时间间隔,该函数会使程序暂停指定的毫秒数,以便让用户观察到像素点的变化效果。
  • 最后当用户按下任意键时,程序退出循环并结束执行。

12.3 运行结果

13. puts

13.1 函数说明

函数声明 函数功能
int puts(const char *s); 用于将一个字符串输出到标准输出流

参数:

  • s: 要输出的以 '\0' 结尾的字符串

返回值:

  • 成功输出的字符数(包括换行符)

13.2 演示示例

1
2
3
4
5
6
7
#include <stdio.h>

int main() {
char *str = "Hello, world!";
puts(str);
return 0;
}

注意: 在输出字符串时,puts() 函数会自动将字符串的内容和换行符写入到标准输出流中,因此不需要再进行额外的操作。如果要将字符串输出到文件或其他输出流中,则可以使用 fputs() 函数。

13.3 运行结果

14. putw

14.1 函数说明

函数声明 函数功能
int putw(int w, FILE *stream); 用于将一个整数值以二进制形式写入到指定的文件中。

参数:

  • w : 要写入的整数值
  • stream : 指向要写入的文件的指针。

返回值:

  • 如果成功,则返回写入的字节数(通常为 4 个字节);
  • 如果发生错误,则返回 EOF

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

int main() {
int num = 42;
FILE *fp = fopen("output.bin", "wb");

putw(num, fp);

fclose(fp);
return 0;
}

在上述的示例中,

  • 我们首先定义了一个整数变量,并使用 fopen() 函数打开一个名为 "output.bin" 的二进制文件;
  • 接着,我们调用 putw() 函数将整数值写入到该文件中;
  • 最后关闭文件并结束程序。

注意: 由于 putw() 函数是以二进制形式写入数据的,因此相对于文本文件而言,它更适合用于存储数字、结构体等复杂类型的数据。如果要将字符串或其他文本数据写入到文件中,则可以使用 fprintf() 函数。

14.3 运行结果

参考

  1. [API Reference Document]

C语言函数大全--o 开头的函数

总览

函数声明 函数功能
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); 在指定位置显示一字符串

1. obstack_init,obstack_free,obstack_alloc,obstack_blank,obstack_grow

1.1 函数说明

函数声明 函数功能
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.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <obstack.h>

int main(void)
{
struct obstack my_obstack;
const char *str1 = "Hello, ";
const char *str2 = "World!";
char *dst;

obstack_init(&my_obstack);

dst = (char *)obstack_alloc(&my_obstack, strlen(str1) + strlen(str2) + 1);
strcpy(dst, str1);
strcat(dst, str2);

printf("%s\n", (char *)my_obstack.chunk);

dst = (char *)obstack_blank(&my_obstack, sizeof(int)*2);
int a = 100;
int b = 200;
memcpy(dst, &a, sizeof(int));
memcpy(dst+sizeof(int), &b, sizeof(int));

printf("%d %d\n", *(int *)(my_obstack.next_free-sizeof(int)*2), *(int *)(my_obstack.next_free-sizeof(int)));

double d = 3.1415926;
dst = (char *)obstack_grow(&my_obstack, &d, sizeof(double));

printf("%f\n", *(double *)(my_obstack.next_free-sizeof(double)));

obstack_free(&my_obstack, NULL);

return 0;
}

在上述的程序中,

  • 我们首先定义一个名为 my_obstackstruct obstack 类型变量,并将其传递给 obstack_init() 函数以初始化对象堆栈。
  • 接着,我们使用 obstack_alloc() 函数从对象堆栈中分配一块内存,并将两个字符串连接起来。
  • 然后,我们使用 obstack_blank() 函数向对象堆栈添加一块指定大小的空间,并使用 memcpy() 函数将两个整数复制到该空间中。
  • 接下来,我们使用 obstack_grow() 函数向对象堆栈添加一个双精度浮点数,并返回指向该浮点数的指针。
  • 最后,我们使用 printf() 函数将连接后的字符串、添加的整数和添加的双精度浮点数输出到终端,并使用 obstack_free() 函数释放通过对象堆栈分配的所有内存。

注意:在使用 obstack_blank() 函数向对象堆栈添加空间时,建议使用 sizeof 运算符来计算要添加的空间大小,并在使用 memcpy() 复制数据时也应该小心不要越界。同时,在使用 obstack_grow() 函数向对象堆栈添加数据时,需要小心指针是否正确,并且操作前需要先使用 memcpy() 将要添加的数据复制到一个临时变量中。

2. offsetof

2.1 宏说明

宏定义 宏描述
#define offsetof(type, member) ((size_t)(&((type *)0)->member)) 它是一个宏,用于获取结构体中某个成员的偏移量。

参数:

  • type : 表示结构体类型
  • member : 表示结构体中的一个成员变量名

返回值: 一个 size_t 类型的值,表示该成员变量在结构体中的偏移量(单位是字节)。

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stddef.h>

struct example {
int a;
char b;
double c;
};

int main(void)
{
size_t offset_b = offsetof(struct example, b);
printf("Offset of 'b' in struct example: %zu\n", offset_b);

return 0;
}

在这个程序中,

  • 我们定义了一个名为 example 的结构体类型,并使用 offsetof 宏获取结构体中成员变量 b 的偏移量。
  • 最后,我们使用 printf() 函数将结果输出到终端。

注意: 在使用 offsetof 宏时,结构体类型名称必须使用括号括起来,否则代码会产生语法错误。此外,offsetof 宏的参数必须是已定义的结构体类型名称和该结构体类型中的成员变量名称,否则也会导致编译错误。

3. open

3.1 函数说明

函数声明 函数功能
int open(const char *path, int oflag, ...); 用于打开文件

参数:

  • path : 表示要打开的文件路径
  • oflag : 表示打开文件时的选项标志,可以为以下常量之一或多个按位或组合而成:
    • O_RDONLY:只读模式打开文件。
    • O_WRONLY:只写模式打开文件。
    • O_RDWR:读写模式打开文件。
    • O_CREAT:如果文件不存在,则创建它。
    • O_TRUNC:如果文件已存在,则将其长度截断为 0。
    • O_APPEND:在文件末尾追加数据。
  • 可选参数 : 表示文件所有者、组和其他用户的访问权限。如果使用了 O_CREAT 选项,则必须提供这个参数

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(void)
{
int fd = open("temp.txt", O_RDONLY);
if (fd == -1) {
perror("open");
exit(1);
}

char buf[1024];
ssize_t nread;
while ((nread = read(fd, buf, sizeof(buf))) > 0) {
if (write(STDOUT_FILENO, buf, nread) != nread) {
perror("write");
exit(1);
}
}

if (nread == -1) {
perror("read");
exit(1);
}

if (close(fd) == -1) {
perror("close");
exit(1);
}

return 0;
}

在上述的程序中,

  • 我们使用 open() 函数打开文件 temp.txt,并通过 read() 函数读取其中的数据。
  • 然后,我们使用 write() 函数将数据写入标准输出,直到读取完整个文件。
  • 最后,我们使用 close() 函数关闭文件。

注意: 在使用 open() 函数打开文件时,返回值为负数则表示出现了错误。此时可以使用 perror() 函数输出错误信息,并使用 exit() 函数退出程序。同时,在使用 read() 函数和 write() 函数读写文件时也需要小心处理返回值,以避免出现不可预期的错误。

3.3 运行结果

4. openat

4.1 函数说明

函数声明 函数功能
int openat(int dirfd, const char *pathname, int flags, mode_t mode); 它是 Linux 系统定义的一个函数,它可以打开一个相对于指定目录的文件。与 open() 函数相比,openat() 函数更加灵活,并支持更多的选项。

参数:

  • dirfd : 表示要打开文件所在目录的文件描述符。如果传递的是 AT_FDCWD,则表示使用当前工作目录。
  • pathname : 表示要打开的文件路径
  • flags : 表示打开文件时的选项标志,可以为以下常量之一或多个按位或组合而成:
    • O_RDONLY:只读模式打开文件。
    • O_WRONLY:只写模式打开文件。
    • O_RDWR:读写模式打开文件。
    • O_CREAT:如果文件不存在,则创建它。
    • O_TRUNC:如果文件已存在,则将其长度截断为 0。
    • O_APPEND:在文件末尾追加数据。
    • O_DIRECTORY:要求打开的文件必须是一个目录。
    • O_NOFOLLOW:不跟随符号链接打开文件。
  • mode : 表示文件所有者、组和其他用户的访问权限。如果使用了 O_CREAT 选项,则必须提供这个参数

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <dirent.h>

int main(void)
{
int dirfd = open(".", O_RDONLY | O_DIRECTORY);
if (dirfd == -1) {
perror("open");
exit(1);
}

DIR *dirp = fdopendir(dirfd);
if (dirp == NULL) {
perror("fdopendir");
exit(1);
}

struct dirent *entry;
while ((entry = readdir(dirp)) != NULL) {
printf("%s\n", entry->d_name);
}

if (closedir(dirp) == -1) {
perror("closedir");
exit(1);
}

return 0;
}

在这个程序中,

  • 我们使用 openat() 函数打开当前目录,并通过 fdopendir() 函数将文件描述符转换为目录流。
  • 然后,我们使用 readdir() 函数读取目录中的文件,并将文件名输出到终端。
  • 最后,我们使用 closedir() 函数关闭目录。

注意: 在使用 openat() 函数打开文件时,可以通过传递不同的文件描述符指定要打开的目录,从而实现更加灵活的操作。此外,在使用 readdir() 函数读取目录时也需要注意判断返回值是否为 NULL,以避免出现不可预期的错误。

5. opendir

5.1 函数说明

函数声明 函数功能
DIR *opendir(const char *name); 它是 POSIX 标准定义的一个函数,用于打开目录并返回一个指向 DIR 结构体类型的指针。

参数:

  • name : 表示要打开的目录路径

返回值:

  • 如果该函数执行成功,则返回一个指向 DIR 类型的指针;
  • 否则返回 NULL

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>

int main(void)
{
DIR *dirp = opendir(".");
if (dirp == NULL) {
perror("opendir");
exit(1);
}

struct dirent *entry;
while ((entry = readdir(dirp)) != NULL) {
printf("%s\n", entry->d_name);
}

if (closedir(dirp) == -1) {
perror("closedir");
exit(1);
}

return 0;
}

在上述的程序中,我们使用 opendir() 函数打开当前目录,并通过 readdir() 函数读取目录中的文件名,最后使用 closedir() 函数关闭目录。

注意: 在使用 opendir() 函数打开目录时,返回值为 NULL 则表示出现了错误。此时可以使用 perror() 函数输出错误信息,并使用 exit() 函数退出程序。同时,在使用 readdir() 函数读取目录时也需要小心处理返回值,以避免出现不可预期的错误。

6. openpty

6.1 函数说明

函数声明 函数功能
int openpty(int *amaster, int *aslave, char *name, const struct termios *termp, const struct winsize *winp); 它是 POSIX 标准定义的一个函数,用于打开一个伪终端(PTY)并返回与之关联的主从设备文件描述符。伪终端可以用于在进程之间建立通信,或者在程序中模拟终端行为。

参数:

  • amaster : 表示要返回的主设备文件描述符
  • aslave : 表示要返回的从设备文件描述符
  • name : 表示从设备名称的缓冲区,如果不需要则可以传递 NULL
  • termp : 表示要使用的终端属性,如果不需要则可以传递 NULL
  • winp : 表示要使用的窗口大小,如果不需要则可以传递 NULL

返回值:

  • 如果该函数执行成功,则返回值为 0
  • 否则返回 -1

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

int main(void)
{
int master, slave;
char buf[1024];
ssize_t nread;

if (openpty(&master, &slave, NULL, NULL, NULL) == -1) {
perror("openpty");
exit(1);
}

printf("Slave device: /dev/pts/%d\n", slave);

while ((nread = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
if (write(master, buf, nread) != nread) {
perror("write");
exit(1);
}
}

if (nread == -1) {
perror("read");
exit(1);
}

if (close(master) == -1) {
perror("close");
exit(1);
}

return 0;
}

在上述的程序中,

  • 我们使用 openpty() 函数打开一个伪终端,并通过 read() 函数读取标准输入中的数据。
  • 然后,我们将数据写入主设备文件描述符;
  • 最后关闭该设备。

注意: 在使用 openpty() 函数打开伪终端时,返回值为 -1 则表示出现了错误。此时可以使用 perror() 函数输出错误信息,并使用 exit() 函数退出程序。同时,在使用 read() 函数和 write() 函数读写文件时也需要小心处理返回值,以避免出现不可预期的错误。

7. on_exit

7.1 函数说明

函数声明 函数功能
int on_exit(void (*function)(int, void *), void *arg); 它是 POSIX 标准定义的一个函数,用于在进程退出时调用注册的回调函数。这个函数可以用于在程序异常退出或者正常退出时执行一些清理工作、记录日志等操作

参数:

  • function : 表示要注册的回调函数
  • arg : 表示传递给回调函数的参数

返回值:

  • 如果该函数执行成功,则返回值为 0
  • 否则返回 -1

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void cleanup(int status, void *arg)
{
printf("Cleanup function called with status %d\n", status);
}

int main(void)
{
if (on_exit(cleanup, NULL) != 0) {
perror("on_exit");
exit(EXIT_FAILURE);
}

printf("This is the main program\n");

return 0;
}

在如上的程序中,

  • 我们使用 on_exit() 函数注册了一个回调函数 cleanup(),并将其参数设置为 NULL。
  • 然后,在主函数中输出了一条消息。当程序退出时,会自动调用回调函数来进行清理操作。

8. outtext

8.1 函数说明

函数声明 函数功能
void outtext(char *textstring); 在图形视区显示一个字符串

参数:

  • char *textstring :指向以空字符(’\0’)结尾的字符串的指针。

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode, errorcode;
int midx, midy;

initgraph(&gdriver, &gmode, "");

midx = getmaxx() / 2;
midy = getmaxy() / 2;

moveto(midx, midy);

outtext("This ");
outtext("is ");
outtext("a ");
outtext("test.");

getch();
closegraph();
return 0;
}

在上述的程序中,

  • 我们首先调用 initgraph() 函数初始化图形系统;
  • 然后获取窗口的中心坐标;
  • 接着使用 moveto() 函数将当前绘图位置移动到屏幕中心。
  • 最后,使用 outtext() 函数输出一段文字,然后等待用户按下任意键,并关闭图形窗口。

8.3 运行结果

9. outtextxy

9.1 函数说明

函数声明 函数功能
void outtextxy(int x, int y, char *textstring); 在指定位置显示一字符串

参数:

  • int x : 字符串输出的水平起始坐标(单位为像素)。取值范围:与当前图形模式的屏幕分辨率相关(例如,640x480 模式下,x 范围为 0 到 639)。

  • int y : 字符串输出的垂直起始坐标(单位为像素)。取值范围:与当前图形模式的屏幕分辨率相关(例如,480p 模式下,y 范围为 0 到 479)。

  • char *textstring : 指向以空字符(’\0’)结尾的字符串的指针。

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode, errorcode;
int x, y;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;

outtextxy(x, y, "Hello, world!");

getch();
closegraph();
return 0;
}

在上述这个程序中,

  • 我们首先通过 initgraph() 函数初始化图形系统并创建一个窗口;
  • 然后,定义了一个坐标位置 (x, y) 并使用 outtextxy() 函数在该位置输出一段文本。
  • 最后,使用 getch 函数等待用户按下任意键,然后关闭图形窗口。

9.3 运行结果

C语言函数大全--n 开头的函数

总览

函数声明 函数功能
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); 用于将网络字节序(大端序)转换为主机字节序(小端序)。

1. nan

1.1 函数说明

函数声明 函数功能
double nan(const char *tagp); 用于返回一个表示 NaN(非数值)的 double 类型数字

参数:

  • tagp : 指向字符串的指针;用于指定 NaN 数字的类型。如果不需要指定类型,则可以将该参数设置为 NULL。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <math.h>

int main(void)
{
double x = 0.0 / 0.0; // 使用除 0 运算符来生成 NaN 数字
printf("x: %f\n", x);

double y = nan(NULL); // 使用 nan() 函数来生成 NaN 数字
printf("y: %f\n", y);

return 0;
}

注意: NaN 数字具有一些特殊的属性,例如与任何数字进行比较都会返回 false,因此在实际编程中需要特别小心处理 NaN 的情况,避免出现异常结果

1.3 运行结果

2. nanosleep

2.1 函数说明

函数声明 函数功能
int nanosleep(const struct timespec *req, struct timespec *rem); 用于暂停当前进程的执行一段指定的时间。相比于 sleep() 函数,nanosleep() 函数可以精确地指定等待时间,以纳秒为单位。

参数:

  • req : 指向 timespec 结构体的指针,用于指定要等待的时间。timespec 结构体包含两个成员变量:tv_sec 表示等待时间的整数部分(秒),tv_nsec 表示等待时间的小数部分(纳秒)。如果 rem 参数不为 NULL,则在函数返回时,未完成的等待时间将被存储在 rem 指向的 timespec 结构体中。
  • rem : 未完成的等待时间

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <time.h>

int main(void)
{
struct timespec req = { 0 };
req.tv_sec = 2; // 等待时间为 2 秒
req.tv_nsec = 5000000; // 加上 5 毫秒

int ret = nanosleep(&req, NULL);
if (ret == 0) {
printf("nanosleep completed\n");
} else {
printf("nanosleep interrupted by signal\n");
}

return 0;
}

在上述的程序中,

  • 我们首先创建一个 timespec 结构体变量 req,用于指定等待时间。在本例中,我们将等待时间设置为 2 秒加上 5 毫秒。
  • 接着,我们调用 nanosleep() 函数,并传递 req 变量的地址作为第一个参数。如果函数执行成功(即完成了预定的等待时间),则返回值为 0,否则返回 -1
  • 最后,我们检查函数的返回值,以确定 nanosleep() 是否成功完成。如果返回值为 0,则表示函数已经完成了预定的等待时间;如果返回值为 -1,则说明函数被信号中断。在实际编程中,我们还可以通过检查 errno 变量来获取更具体的错误信息。

3. nearbyint,nearbyintf,nearbyintl

3.1 函数说明

函数声明 函数功能
double nearbyint(double x); 用于将一个浮点数四舍五入到最接近的整数值(double)
float nearbyintf(float x); 用于将一个浮点数四舍五入到最接近的整数值(float)
long double nearbyintl(long double x); 用于将一个浮点数四舍五入到最接近的整数值(long double)

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <math.h>

int main(void)
{
double x = 2.3;
double y = -1.8;

double z = nearbyint(x); // 将 2.3 四舍五入到 2
double w = nearbyint(y); // 将 -1.8 四舍五入到 -2

printf("x: %lf, nearbyint(x): %lf\n", x, z);
printf("y: %lf, nearbyint(y): %lf\n", y, w);

float xf = 2.5;
printf("xf: %f, nearbyintf(xf): %f\n", xf, nearbyintf(xf));

long double xL = -1.3;
printf("xL: %Lf, nearbyintl(xL): %Lf\n", xL, nearbyintl(xL));

return 0;
}

注意: nearbyint() 函数对于 0.5 的情况具有特殊处理:如果要转换的数恰好与两个整数的距离相等,则按照偶数方向进行舍入(即选择更接近偶数的整数)。例如,如果要将 2.5 转换为整数,那么将近似到最接近的偶数 2,而不是 3。这种舍入方式称为 “银行家舍入法”“四舍六入五成双”

3.3 运行结果

4. nextafter,nextafterf,nextafterl

4.1 函数说明

函数声明 函数功能
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)

参数:

  • x : 要查找其下一个浮点数的浮点数
    • y : 给定浮点数的目标值,表示前进方向。

返回值:

  • 如果 y 大于 x,则向正无穷方向查找;
  • 如果 y 小于 x,则向负无穷方向查找;如果 y 等于 x,则返回 y

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <math.h>

int main(void)
{
double x = 1.0;
double y = 2.0;

printf("nextafter(%lf, %lf): %.20lf\n", x, y, nextafter(x, y));
printf("nextafter(%lf, %lf): %.20lf\n", y, x, nextafter(y, x));

float xf = 2.0;
float yf = 1.0;
printf("nextafterf(%f, %f): %.20f\n", xf, yf, nextafterf(xf, yf));

long double xL = -1.2;
long double yL = - 1.5;
printf("nextafterl(%Lf, %Lf): %.20Lf\n", xL, yL, nextafterl(xL, yL));

return 0;
}

注意: 由于计算机内部存储浮点数的方式是有限制的,因此在进行浮点数计算时可能会存在误差。在实际编程中,我们应该特别小心处理这些情况,避免出现异常结果。

4.3 运行结果

5. nexttoward,nexttowardf,nexttowardl

5.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)

参数:

  • x : 要查找其下一个浮点数的浮点数
  • y : 给定浮点数的目标值,表示前进方向。

返回值:

  • 如果 y 大于 x,则向正无穷方向查找;
  • 如果 y 小于 x,则向负无穷方向查找;如果 y 等于 x,则返回 y

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>

int main(void)
{
double x = 1.0;
long double y = 2.0;

printf("nexttoward(%lf, %Lf): %.20lf\n", x, y, nexttoward(x, y));

float xf = 3.2;
printf("nexttowardf(%f, %Lf): %.20f\n", xf, y, nexttowardf(xf, y));

long double xL = 1.9;
printf("nexttowardl(%Lf, %Lf): %.20Lf\n", xL, y, nexttowardl(xL, y));

return 0;
}

5.3 运行结果

6. newlocale

6.1 函数说明

函数声明 函数功能
locale_t newlocale(int category_mask, const char *locale, locale_t base); 用于创建并返回一个新的本地化环境变量,以便在不同的本地化设置之间进行切换。

参数:

  • category_mask : 指定了要创建的本地化环境变量包含哪些类别。可以使用下列常量按位或来指定:
    • LC_ALL_MASK:表示所有类别。
    • LC_COLLATE_MASK:表示字符串比较和排序规则。
    • LC_CTYPE_MASK:表示字符分类和转换规则。
    • LC_MESSAGES_MASK:表示本地化消息文本。
    • LC_MONETARY_MASK:表示货币格式。
    • LC_NUMERIC_MASK:表示数字格式。
    • LC_TIME_MASK:表示时间和日期格式。
  • locale : 指定了要使用的区域设置名称。如果为 NULL 或空字符串,则使用当前系统默认的本地化设置。
  • base : 指定了要基于的基础本地化环境变量。如果为 NULL,则使用 LC_GLOBAL_LOCALE

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <locale.h>

int main()
{
// 创建一个新的本地化环境变量,用于解析德语字符串比较和排序规则。
locale_t loc = newlocale(LC_COLLATE_MASK, "de_DE.UTF-8", LC_GLOBAL_LOCALE);

// 在新的本地化环境变量下比较两个字符串,并输出比较结果。
const char *str1 = "äbc";
const char *str2 = "abc";
int result = strcoll_l(str1, str2, loc);
printf("%s %s %s\n", str1, (result < 0 ? "<" : (result > 0 ? ">" : "==")), str2);

// 释放本地化环境变量
freelocale(loc);

return 0;
}

在上述程序中,

  • 我们首先使用 newlocale() 函数创建一个新的本地化环境变量 loc,以便比较和排序德语字符串。
  • 接着,我们使用 strcoll_l() 函数来在新的本地化环境变量下比较两个字符串 str1str2
  • 最后,我们输出比较结果,并使用 freelocale() 函数释放 loc 变量。

注意: 在实际编程中应该特别注意本地化设置对字符处理、货币格式、时间格式等方面的影响,避免出现不必要的错误。

7. nftw

7.1 函数说明

函数声明 函数功能
int nftw(const char *dirpath, int (*fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf), int nopenfd, int flags); 用于递归遍历指定目录下的所有文件和子目录,并对每个文件或目录执行指定操作。

参数:

  • dirpath : 要遍历的目录路径
  • fn : 一个回调函数,用于在遍历过程中对每个文件或目录执行指定操作。该函数的参数如下:
    • fpath : 当前文件的完整路径。
    • sb : 当前文件的 struct stat 结构体指针,包含了当前文件的各种属性信息。
    • typeflag : 表示当前文件的类型,可能为以下值之一:
      • FTW_F:普通文件。
      • FTW_D:目录。
      • FTW_DNR:无法读取的目录。
      • FTW_NS:无法访问的文件(可能是因为权限问题)。
      • FTW_SL:符号链接。
      • FTW_DP:与 FTW_D 相同,但目录本身还未被访问。
      • FTW_SLN:符号链接,指向不存在的文件。
    • ftwbuf : 一个 struct FTW 结构体指针,包含了一些关于遍历状态的信息。
  • nopenfd : 最大打开文件描述符数
  • flags : 控制遍历行为的标志位,可以使用下列常量按位或来指定:
    • FTW_CHDIR:进入目录后更改工作目录。
    • FTW_DEPTH:深度优先遍历。
    • FTW_MOUNT:不跨越文件系统边界。
    • FTW_PHYS:不跟随符号链接。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <ftw.h>

static int count = 0;

int print_file_info(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
{
// 打印文件路径和类型
printf("%s ", fpath);
if (typeflag == FTW_F) {
printf("(file)\n");
} else if (typeflag == FTW_D) {
printf("(dir)\n");
} else {
printf("(other)\n");
}

// 计数器加一
count++;

return 0;
}

int main(void)
{
int result = nftw(".", print_file_info, 10, FTW_PHYS);

if (result == -1) {
perror("nftw");
exit(EXIT_FAILURE);
}

printf("Total files and directories: %d\n", count);

return 0;
}

在上述的程序中,

  • 我们首先定义了一个回调函数 print_file_info(),用于打印每个文件或目录的路径和类型,并将计数器加一。
  • 接着,我们调用 nftw() 函数来递归遍历当前目录下的所有文件和子目录,并对每个文件或目录执行 print_file_info() 函数。
  • 最后,我们输出遍历总数。

注意: 在实际编程中应该特别注意文件访问权限等问题,以避免出现不必要的错误。

7.3 运行结果

8. nice

8.1 函数说明

函数声明 函数功能
int nice(int inc); 它是一个系统调用,可将进程截止到当前用户的最大优先级减少指定的优先级,以更改进程的调度优先级。较高的 niceness 值意味着较低的优先级。

参数:

  • inc : 要增加或减少的优先级值。如果 inc 的值为正数,则表示将进程的优先级降低;如果 inc 的值为负数,则表示将进程的优先级提高。通常情况下,只有具有 root 权限的进程才能将自己的优先级升高。

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <unistd.h>

int main(void)
{
// 输出当前进程的初始优先级
printf("Initial nice value: %d\n", nice(0));

// 将进程的优先级减少 10
int result = nice(10);
if (result == -1) {
perror("nice");
} else {
printf("New nice value: %d\n", result);
}

return 0;
}

在上述程序中,

  • 我们首先使用 nice(0) 函数输出当前进程的初始优先级;
  • 接着,我们使用 nice(10) 函数将进程的调度优先级降低 10
  • 最后将新的优先级值输出到终端。

注意: 由于 nice() 函数并不是标准 C 库中的函数,因此在编译时需要传递 -posix 参数或其他类似参数以启用 POSIX 标准。在实际编程中应该特别注意优先级修改对进程正常运行的影响,以避免出现不必要的错误。

9. nl_langinfo

9.1 函数说明

函数声明 函数功能
char *nl_langinfo(nl_item item); 它是一个 POSIX 标准函数,用于获取当前本地化环境下的语言环境信息。它可以返回一些与语言、货币、日期和时间格式等相关的信息。

参数:

  • item : 指定要获取的本地化信息。可以使用下列常量之一来指定:
    • 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:非十进制数字字符。

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <langinfo.h>

int main(void)
{
char *time_fmt = nl_langinfo(T_FMT);
char *date_fmt = nl_langinfo(D_FMT);

printf("Time format: %s\n", time_fmt);
printf("Date format: %s\n", date_fmt);

return 0;
}

在上述的程序中,

  • 我们使用 nl_langinfo(T_FMT) 函数获取当前本地化环境下的时间格式字符串,并将其输出到终端。
  • 接着,我们使用 nl_langinfo(D_FMT) 函数获取当前本地化环境下的日期格式字符串,并将其输出到终端。

注意: 在实际编程中应该特别注意处理不同本地化环境下信息的差异,以避免出现不必要的错误。

10. nrand48

10.1 函数说明

函数声明 函数功能
long nrand48(unsigned short xsubi[3]); 用于生成带有指定状态的随机数。它使用 48 位整数来表示随机数的状态,可以方便地切换不同的随机数生成器状态。

参数:

  • xsubi : 一个包含 316 位无符号整数的数组,表示了当前随机数生成器的状态。如果想更改随机数生成器的状态,只需修改 xsubi 数组即可。

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
unsigned short seed[3];
seed[0] = (unsigned short) time(NULL);
seed[1] = (unsigned short) getpid();
seed[2] = 12345;

srand48(seed);

printf("Random number: %ld\n", nrand48(seed));

return 0;
}

在上述的程序中,

  • 我们首先创建了一个包含 316 位无符号整数的数组 seed,并将其用作随机数生成器的种子。
  • 接着,我们使用 srand48() 函数初始化随机数生成器,并使用 nrand48() 函数生成一个随机数,并将其输出到终端。

注意: 由于 nrand48() 函数生成的是伪随机数,因此在实际使用时需要注意选择足够复杂的种子,并采取适当的加密措施以避免出现不必要的安全问题。

11. ntohl,ntohs

11.1 函数说明

函数声明 函数功能
uint32_t ntohl(uint32_t netlong); 用于将网络字节序(大端序)转换为主机字节序(小端序)。
uint16_t ntohs(uint16_t netshort); 用于将网络字节序(大端序)转换为主机字节序(小端序)。

参数:

  • netlong : 表示要转换的 32 位整数。
  • netshort : 表示要转换的 16 位整数。

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdint.h>
#include <netinet/in.h>

int main(void)
{
uint32_t num1 = 0x12345678;
uint16_t num2 = 0x5678;

printf("Original value (hex):\n");
printf("num1: %08X\n", num1);
printf("num2: %04X\n", num2);

num1 = ntohl(num1);
num2 = ntohs(num2);

printf("Converted value (hex):\n");
printf("num1: %08X\n", num1);
printf("num2: %04X\n", num2);

return 0;
}

注意: 在实际编程中应该特别注意不同平台之间的字节序差异,以避免出现不必要的错误。

C语言函数大全--m 开头的函数(下)

总览

函数声明 函数功能
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()函数锁定的内存区域解锁,使其可被操作系统交换出去或被回收

1. mkdirat

1.1 函数说明

函数声明 函数功能
int mkdirat(int dirfd, const char *pathname, mode_t mode); 它是一个 Linux 系统下的系统调用函数,用于在指定目录下创建新的子目录

参数:

  • dirfd : 要在其下创建新目录的父目录的文件描述符。如果值为 AT_FDCWD,则表示使用当前工作目录
  • pathname : 要创建的新目录的名称和路径
  • mode : 要创建的新目录的权限模式

返回值:

  • 如果成功创建新目录时,则返回 0
  • 如果失败时,则返回 -1,并设置错误码(errno)。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>

int main()
{
int dirfd;
if ((dirfd = open("/tmp", O_RDONLY)) == -1)
{
printf("Error opening directory.\n");
return 1;
}

if (mkdirat(dirfd, "testdir", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
{
printf("Error creating directory.\n");
return 1;
}

close(dirfd);
return 0;
}

在上述的示例代码中,

  • 首先,我们打开 /tmp 目录并获取其文件描述符 dirfd
  • 然后,我们调用 mkdirat() 函数,并将目录的文件描述符、要创建的新目录的名称和路径以及目录的权限模式作为参数传递给函数。如果函数调用成功,则新目录将在 /tmp 目录下创建。
  • 最后,调用 close() 函数关闭文件。

注意:

  • 使用 mkdirat() 函数时,我们需要确保指定的父目录存在并具有适当的权限。
  • 如果要使用相对路径创建新目录,需要确保当前工作目录正确设置。

2. mkfifo

2.1 函数说明

函数声明 函数功能
int mkfifo(const char *pathname, mode_t mode); 它是一个 Linux 系统下的系统调用函数,用于创建命名管道

参数:

  • pathname : 要创建的命名管道的名称和路径
  • mode : 命名管道的权限模式

返回值:

  • 如果成功创建命名管道时,则返回 0
  • 如果失败时,则返回 -1,并设置错误码(errno)。

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>

int main()
{
// 如果函数调用成功,则在 /tmp 目录下创建一个名为 myfifo 的命名管道
if (mkfifo("/tmp/myfifo", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) == -1)
{
printf("Error creating named pipe.\n");
return 1;
}

return 0;
}

注意:

  • 使用 mkfifo() 函数时,我们需要确保指定的路径可被访问并且不存在同名的文件或目录。
  • 如果要使用相对路径创建命名管道,需要确保当前工作目录正确设置。

3. mkstemp

3.1 函数说明

函数声明 函数功能
int mkstemp(char *template); 用于在磁盘上创建一个唯一的临时文件并打开它以进行读写

参数:

  • template : 指向包含 6 个连续 'X' 的字符串的指针,这些 'X' 将被替换为随机字符以创建唯一的文件名。例如,"/tmp/tempfile-XXXXXX" 将会被替换为类似 "/tmp/tempfile-5ZqYU2" 的唯一文件名。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
char temp_file_template[] = "tmp/tempfile-XXXXXX";
int fd;

if ((fd = mkstemp(temp_file_template)) == -1)
{
printf("Error creating temporary file.\n");
return 1;
}

printf("Temporary file created: %s\n", temp_file_template);

// 读写临时文件

// 关闭临时文件
close(fd);
return 0;
}

如上演示了,在 windows 下 创建临时文件:

  • 首先,我们定义了一个字符串 temp_file_template,它包含连续的 6'X'
  • 接着,我们调用 mkstemp() 函数,并将指向 temp_file_template 的指针作为参数传递给函数。如果函数调用成功,则返回新创建文件的文件描述符,并将 temp_file_template 中的 'X' 替换为随机字符以形成唯一的文件名;
  • 然后,调用 printf() 函数,输出该临时文件的名称;
  • 再接着,可以使用 fd 来操作临时文件【这里示例省略了】;
  • 再然后,临时文件使用完毕,调用 close() 函数关闭临时文件。
  • 最后,返回 0 表示程序执行成功。

注意: 在使用 mkstemp() 函数时,我们需要确保提供的模板字符串至少包含 6'X',并且文件命名方式不能与现有文件冲突。

3.3 运行结果

4. mkdir

4.1 函数说明

函数声明 函数功能
int mkdir(const char *pathname, mode_t mode); 它是一个 Linux 系统下的系统调用函数,用于创建新目录
int mkdir(const char *pathname); 它是在 Windows 系统下的系统调用函数,用于创建新目录

参数:

  • pathname: 要创建的新目录的名称和路径
  • mode : 要创建的新目录的权限模式

返回值:

  • 如果成功创建新目录时,则返回 0
  • 如果失败时,则返回 -1,并设置错误码(errno)。

4.2 演示示例

4.2.1 Windows 下示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>

int main()
{
if (mkdir("tmp/newdir") == -1)
{
printf("Error creating new directory.\n");
return 1;
}

return 0;
}

4.2.1 Linux 下示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

int main()
{
if (mkdir("/tmp/newdir", S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == -1)
{
printf("Error creating new directory.\n");
return 1;
}

return 0;
}

4.3 运行结果

Windows 下示例运行结果

5. mktime

5.1 函数说明

函数声明 函数功能
time_t mktime(struct tm *timeptr); 用于将表示时间的结构体(struct tm)转换为对应的 Unix 时间戳

参数:

  • timeptr : 指向 struct tm 结构体的指针,其中包含要转换为 Unix 时间戳的日期和时间信息

返回值:

  • 如果转换成功,则返回对应于输入时间的 Unix 时间戳;
  • 如果转换失败,则返回 -1

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
struct tm my_time = {0}; // 初始化为 0,避免随机值影响结果
my_time.tm_year = 2023 - 1900; // 年份应该减去 1900
my_time.tm_mon = 4 - 1; // 月份从 0 开始计数,应该减去 1
my_time.tm_mday = 15;
my_time.tm_hour = 10;
my_time.tm_min = 30;
my_time.tm_sec = 0;

time_t timestamp = mktime(&my_time);
if (timestamp == -1)
{
printf("Error converting time to timestamp.\n");
return 1;
}

printf("Unix timestamp: %lld\n", timestamp);

return 0;
}

在上面的示例代码中,

  • 首先,我们创建一个 struct tm 结构体 my_time,并将其初始化为 0
  • 然后,设置结构体的年、月、日、时、分、秒等信息。这里的年份应该减去 1900,月份应该从 0 开始计数减去 1
  • 接着,调用 mktime() 函数,并将指向 my_time 结构体的指针作为参数传递给函数。如果函数调用成功,则返回对应于输入时间的 Unix 时间戳。
  • 最后,输出该 Unix 时间戳。

注意:

  • 在使用 mktime() 函数时,我们需要确保提供的 struct tm 结构体中的所有字段都已正确设置。
  • 由于 mktime() 函数所使用的时区可能与系统默认的时区不同,所以在某些情况下,转换结果可能会有一定偏差。

5.3 运行结果

6. mlock

6.1 函数说明

函数声明 函数功能
int mlock(const void *addr, size_t len); 它是一个 Linux 系统下的系统调用函数,用于将指定内存区域锁定在物理内存中,防止其被交换到磁盘上

参数:

  • addr : 要锁定的内存区域的起始地址
  • len : 要锁定的内存区域的长度(字节数)

返回值:

  • 如果成功锁定内存区域时,则返回 0
  • 如果失败时,则返回 -1,并设置错误码(errno)。

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // memset 函数所需头文件
#include <sys/mman.h> // mlock 函数所需头文件

#define PAGE_SIZE 4096 // 页大小

int main()
{
char *buf;
size_t size = PAGE_SIZE;

// 分配一段内存并清零
buf = (char *)malloc(size);
memset(buf, 0, size);

// 锁定分配的内存区域
if (mlock(buf, size) == -1)
{
printf("Error locking memory.\n");
return 1;
}

// 使用分配的内存...
strncpy(buf, "Hello world!", size);
printf("%s\n", buf);

// 解锁内存区域
if (munlock(buf, size) == -1)
{
printf("Error unlocking memory.\n");
return 1;
}

free(buf);
return 0;
}

在上述的示例代码中,

  • 首先,我们使用 malloc() 函数分配了一个页大小的内存区域,并使用 memset() 函数将其清零;
  • 然后,调用 mlock() 函数,并将指向分配内存区域起始地址的指针以及内存区域的长度作为参数传递给函数。如果函数调用成功,则锁定分配的内存区域,防止其被交换到磁盘上;
  • 接着,就可以对该内存区域进行读写操作【示例代码简单演示了使用 strncpy() 函数向上述的分配内存区域中写入字符串 "Hello world!",并通过 printf() 函数输出该字符串】;
  • 再接着,调用 munlock() 函数解除内存区域的锁定;
  • 最后,释放分配内容,并正常结束程序。

注意: 在使用 mlock() 函数时,我们需要确保指定的内存区域已正确分配并且足够大,以避免锁定错误的内存区域。

7. mmap

7.1 函数说明

函数声明 函数功能
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 它是一个 Linux 系统下的系统调用函数,可以将一个文件或者设备映射到内存中,并返回指向该内存区域的指针

参数:

  • addr : 映射区域开始地址,通常为 NULL,由内核选定
  • length : :映射区域的长度(字节数)
  • prot : 映射区域的保护方式。其可能的取值如下【按位或(|)组合】:
    • PROT_NONE: 区域不能被访问。
    • PROT_READ: 区域可被读取。
    • PROT_WRITE: 区域可被写入。
    • PROT_EXEC: 区域可被执行。
  • flags : 制定映射区域的类型和其他标志。其可能的取值如下【按位或(|)组合】:
    • MAP_SHARED: 允许多个进程共享该映射区域,对映射区域所做的修改将反映到所有共享该区域的进程中。
    • MAP_PRIVATE: 该映射区域只允许当前进程进行访问,对映射区域所做的修改不会反映到其他进程中。
    • MAP_FIXED: 强制将映射区域放置在指定的地址处(如果该地址已经被占用,则会导致错误)。
    • MAP_ANONYMOUS: 创建一个匿名映射区域,不与任何文件关联。
    • MAP_FILE: 将映射区域与文件关联,需要指定文件描述符和偏移量。
    • MAP_LOCKED: 指示内核在物理存储器中锁定映射区域的页面,以确保在访问该区域时不会发生缺页中断。
  • fd : 要映射的文件描述符
  • offset : 文件映射的起始偏移量

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
int fd;
char *ptr;

// 打开文件
if ((fd = open("example.txt", O_RDWR)) == -1)
{
printf("Error opening file.\n");
return 1;
}

// 将文件映射到内存中
ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED)
{
printf("Error mapping file.\n");
return 1;
}

// 使用映射区域进行读写操作
strncpy(ptr, "Hello world!", 13);
printf("%s\n", ptr);

// 取消映射并关闭文件
if (munmap(ptr, 4096) == -1)
{
printf("Error unmapping file.\n");
return 1;
}
close(fd);

return 0;
}

上述的示例代码,演示了如何使用 mmap() 函数将一个文件映射到内存中,并使用指针 ptr 访问这个映射区域 :

  • 首先,我们调用 open() 函数打开文件 "example.txt",并检查是否成功打开。
  • 接着,调用 mmap() 函数将文件的前 4096 字节映射到内存中,同时指定保护方式为可读写(PROT_READ | PROT_WRITE)以及共享属性(MAP_SHARED)。
  • 然后,如果映射成功,则使用 strncpy() 函数向映射区域中写入字符串 "Hello world!",并通过 printf() 函数输出该字符串。
  • 最后,调用 munmap() 函数取消映射,并关闭文件。

8. modf,modff,modfl

8.1 函数说明

函数声明 函数功能
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 : 待处理的浮点数
  • iptr : 用于返回 value 的整数部分

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <stdio.h>
#include <math.h>

int main()
{
double x = 3.141592653589793;
double ipart;

double fpart = modf(x, &ipart);

printf("x = %f\n", x);
printf("整数部分 = %.0f\n", ipart);
printf("小数部分 = %f\n", fpart);

float y = 2.718281828459045;
float ipart_f;

float fpart_f = modff(y, &ipart_f);

printf("y = %f\n", y);
printf("整数部分 = %.0f\n", ipart_f);
printf("小数部分 = %f\n", fpart_f);

long double z = 1.414213562373095;
long double ipart_l;

long double fpart_l = modfl(z, &ipart_l);

printf("z = %Lf\n", z);
printf("整数部分 = %.0Lf\n", ipart_l);
printf("小数部分 = %Lf\n", fpart_l);

return 0;
}

8.3 运行结果

9. mount

9.1 函数说明

函数声明 函数功能
int mount(const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, const void *data); 用于将文件系统挂载到指定的挂载点,并返回挂载点的文件描述符

参数:

  • source : 要挂载的文件系统。可以是一个设备文件名、一个目录路径或者 NULL(表示根据 filesystemtype 参数自动选择默认源)
  • target : 要挂载到的目标点,即挂载点
  • filesystemtype : 要挂载的文件系统类型
  • mountflags : 挂载选项
  • data : 任意与文件系统相关的数据

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <sys/mount.h>

int main()
{
int ret;
const char* source = "/dev/sda1";
const char* target = "/mnt/usbdrive";
const char* type = "ext4";

ret = mount(source, target, type, 0, NULL);
if (ret == -1)
{
perror("mount");
return 1;
}

printf("File system mounted successfully!\n");

return 0;
}

在上面的示例代码中,我们调用 mount() 函数将 /dev/sda1 设备文件上的 ext4 文件系统挂载到 /mnt/usbdrive 目录下,并检查挂载操作是否成功。如果 mount() 函数返回值为 -1,则表示挂载失败,通过 perror() 函数输出错误信息并返回 1,程序异常结束;否则,打印 “File system mounted successfully!” 表示挂载成功,并返回 0,程序正常结束。

10. msync

10.1 函数说明

函数声明 函数功能
int msync(void *addr, size_t length, int flags); 用于将指定内存区域的数据同步到文件中

参数:

  • addr : 要同步的内存起始地址
  • length : 要同步的内存区域长度
  • flags : 同步选项,可以是以下值之一:
    • MS_ASYNC: 进行异步写操作(默认选项)
    • MS_SYNC: 进行同步写操作
    • MS_INVALIDATE: 使 cache 内容无效

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>

int main()
{
int fd = open("example.txt", O_RDWR);
if (fd == -1)
{
perror("open");
return 1;
}

// 将文件映射到内存中
char* ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED)
{
perror("mmap");
close(fd);
return 1;
}

// 写入新的数据
strncpy(ptr, "Hello world!", 13);

// 同步数据到文件中
int ret = msync(ptr, 4096, MS_SYNC);
if (ret == -1)
{
perror("msync");
munmap(ptr, 4096);
close(fd);
return 1;
}

// 解除映射并关闭文件
ret = munmap(ptr, 4096);
if (ret == -1)
{
perror("munmap");
close(fd);
return 1;
}
close(fd);

return 0;
}

在上面的示例代码中,

  • 首先,我们通过 open() 函数打开文件 "example.txt"
  • 然后,使用 mmap() 函数将文件的前 4096 字节映射到内存中;
  • 接着,调用 strncpy() 函数向映射区域中写入新的数据,并通过 msync() 函数将修改后的数据同步回磁盘文件;
  • 最后,调用 munmap() 函数解除映射并关闭文件。

11. munmap

11.1 函数说明

函数声明 函数功能
int munmap(void *addr, size_t length); 用于取消内存映射区域,并释放与之相关的资源

参数:

  • addr : 要取消映射的内存起始地址
  • length : 要取消映射的内存区域长度

在调用 munmap() 函数后,操作系统将取消指定的内存映射,并回收相应的资源,包括虚拟地址空间和关联的物理内存页(如果存在)。此外,取消映射还可能导致未同步到磁盘文件中的修改数据丢失。

注意: 必须在对映射区域进行任何修改或者访问之前,先使用 mmap() 函数将文件映射到内存中;并在完成所有操作之后,再使用 munmap() 函数解除映射。否则,可能会引发各种错误或者异常情况。

11.2 演示示例

参见 7.2 的 演示示例,这里不再赘述

12. munlock

12.1 函数说明

函数声明 函数功能
int munlock(const void *addr, size_t len); 用于将之前使用mlock()函数锁定的内存区域解锁,使其可被操作系统交换出去或被回收

参数:

  • addr : 待解锁的内存区域的起始地址
  • len : 待解锁的内存区域的长度(以字节为单位)

返回值:

  • 如果成功解锁时,则返回 0
  • 如果失败时,则返回 -1,并设置错误码(errno)。

注意: 只有拥有相应权限的进程才能解锁该内存区域。

12.2 演示示例

参见 6.2 的 演示示例,这里不再赘述

C语言函数大全--m 开头的函数(上)

总览

函数声明 函数功能
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() 函数会在设置内存块值时检查目标内存块大小,并防止缓冲区溢出、重叠等安全问题。

1. malloc

1.1 函数说明

函数声明 函数功能
void *malloc(size_t size); 用于动态分配内存

参数:

  • size : 需要分配的内存大小(以字节为单位)

返回值:

  • 如果分配成功,返回分配的内存块的指针;
  • 如果分配失败,则返回 NULL。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *str = NULL;

// 分配内存
str = (char *)malloc(20 * sizeof(char));

if (str == NULL)
{
printf("Failed to allocate memory.\n");
return 1;
}

// 将字符串复制到内存中
strcpy(str, "Hello, world!");

// 输出字符串
printf("%s\n", str);

// 释放内存
free(str);

return 0;
}

在上面的示例程序中,

  • 我们首先声明一个指向字符型的指针 str,并将其初始化为 NULL
  • 然后使用 malloc() 函数动态分配了 20 字节的内存空间,并将其赋值给 str 指针;
  • 接下来,我们使用 strcpy() 函数将字符串 "Hello, world!" 复制到内存中,并使用 printf() 函数输出字符串;
  • 最后,我们使用 free() 函数释放了分配的内存空间。

1.3 运行结果

2. mblen

2.1 函数说明

函数声明 函数功能
int mblen(const char *s, size_t n); 检查多字节字符的长度

参数:

  • s : 指向待检查的多字节字符或多字节字符序列的指针
  • n : 要检查的最大字节数

注意: 如果 s 是空指针,则返回 0,表示不是多字节字符;否则,如果 n 不足以包含完整的多字节字符,则返回 -1,表示需要更多的输入;否则,返回多字节字符所需的字节数。

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
int len;

// 检查第一个字符的长度
len = mblen(str, MB_CUR_MAX);

if (len == -1)
{
printf("Failed to determine the length of the multibyte character.\n");
return 1;
}

printf("The length of the first multibyte character is %d bytes.\n", len);

return 0;
}

在上面的示例程序中,

  • 我们首先使用 setlocale() 函数设置本地化环境,以便正确处理多字节字符。
  • 然后我们定义了一个包含中文字符的字符串 str
  • 接着使用 mblen() 函数检查第一个字符的长度,并将其保存到变量 len 中。
  • 最后,我们输出该字符的长度。

2.3 运行结果

3. mbrlen

3.1 函数说明

函数声明 函数功能
size_t mbrlen(const char *s, size_t n, mbstate_t *ps); 检查多字节字符的长度

参数:

  • s : 指向待检查的多字节字符或多字节字符序列的指针
  • n : 要检查的最大字节数
  • ps : 描述转换状态的 mbstate_t 结构体的指针

注意: 如果 s 是空指针,则返回 0,表示不是多字节字符;否则,如果 n 不足以包含完整的多字节字符,则返回 (size_t)-2,表示需要更多的输入;否则,如果 psNULL,则使用默认转换状态;否则,将 ps 的值更新为已经转换的字符数,并返回多字节字符所需的字节数。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <locale.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
int len;

// 检查第一个字符的长度
len = mbrlen(str, MB_CUR_MAX, NULL);

if (len == (size_t)-2) // 特殊的返回值,表示发生了错误
{
printf("Failed to determine the length of the multibyte character.\n");
return 1;
}

printf("The length of the first multibyte character is %d bytes.\n", len);

return 0;
}

在上面的示例程序中,

  • 我们首先使用 setlocale() 函数设置本地化环境,以便正确处理多字节字符。
  • 然后我们定义了一个包含中文字符的字符串 str
  • 接着使用 mbrlen() 函数检查第一个字符的长度,并将其保存到变量 len 中。
  • 最后,我们输出该字符的长度。

3.3 运行结果

4. mbrtowc

4.1 函数说明

函数声明 函数功能
size_t mbrtowc(wchar_t *pwc, const char *s, size_t n, mbstate_t *ps); 将多字节字符转换为宽字符

参数:

  • pwc : 一个指向宽字符的指针,表示将要存入转换后的宽字符;
  • s : 一个指向多字节字符或字符序列的指针;
  • n : 一个表示最多转换的字节数的整数;
  • ps : 一个指向转换状态的指针,如果为 NULL,则使用默认转换状态。

返回值:

  • 如果能转换,返回转换的字符数;
  • 如果不能转换,则返回 (size_t)-1

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
wchar_t wc;
mbstate_t state = {0};

// 将第一个字符转换为宽字符
size_t len = mbrtowc(&wc, str, MB_CUR_MAX, &state);

if (len == (size_t)-1)
{
printf("Failed to convert multibyte character.\n");
return 1;
}

// 输出宽字符
wprintf(L"The first wide character is: %lc\n", wc);

return 0;
}

在上面的示例程序中,

  • 我们首先使用 setlocale() 函数设置本地化环境,以便正确处理多字节字符。
  • 然后我们定义了一个包含中文字符的字符串 str
  • 接着使用 mbrtowc() 函数将第一个字符转换为宽字符,并将其保存到变量 wc 中。
  • 最后,我们使用 wprintf() 函数输出宽字符。

注意: 在调用 mbrtowc() 函数之前,必须将 mbstate_t 结构体的值初始化为 0。在 C99 标准中,可以使用大括号对结构体进行初始化,这会把结构体或数组的每个元素都初始化为默认值(0NULL)。

4.3 运行结果

5. mbsinit

5.1 函数说明

函数声明 函数功能
int mbsinit(const mbstate_t *ps); 检查转换状态是否为起始状态
参数:
  • ps : 指向 mbstate_t 结构体的指针,表示要检查的转换状态。

注意: 如果 ps 是空指针,则返回非零值(真),表示默认转换状态已经初始化;否则,如果 ps 描述的转换状态是起始状态,则返回非零值(真);否则,返回 0(假)。

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
mbstate_t state = {0};

// 检查转换状态是否为起始状态
if (!mbsinit(&state))
{
printf("The conversion state is not initial.\n");
return 1;
}

// 打印转换状态
printf("The conversion state is %s.\n", (mbsinit(&state) ? "initial" : "not initial"));

return 0;
}

在上面的示例程序中,

  • 我们首先定义了一个包含中文字符的字符串 str 和一个转换状态结构体 state
  • 然后我们使用 mbsinit() 函数检查转换状态是否为起始状态;
  • 最后在控制台输出 "The conversion state is initial."

5.3 运行结果

6. mbstowcs

6.1 函数说明

函数声明 函数功能
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n); 用于将多字节字符序列转换为宽字符序列。
参数:
  • pwcs : 指向存储结果宽字符序列的缓冲区的指针
  • s : 待转换的多字节字符序列
  • n : 缓冲区的最大长度(以宽字符数计)

返回值:

  • 如果成功地将多字节字符序列转换为宽字符序列,则该函数返回实际写入缓冲区中的宽字符数,不包括空字符 \0
  • 如果遇到了无效的多字节字符或编码,或者宽字符缓冲区不足,导致转换失败,则该函数返回 (size_t)-1

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
wchar_t wcbuf[20];

// 将多字节字符序列转换为宽字符序列
size_t ret = mbstowcs(wcbuf, str, sizeof(wcbuf)/sizeof(wchar_t));

if (ret == (size_t)-1)
{
printf("Failed to convert multibyte character sequence.\n");
return 1;
}

// 在控制台输出宽字符序列及其长度
wprintf(L"The wide character string is: %ls (%zu characters)\n", wcbuf, ret);

return 0;
}

在上面的示例程序中,我们首先定义了一个包含中文字符的字符串 str 和一个用于存储结果宽字符序列的缓冲区 wcbuf。然后我们使用 mbstowcs() 函数将多字节字符序列转换为宽字符序列,并在控制台输出相应的信息。

注意: 在计算缓冲区大小时,必须将其指定为宽字符数(即 sizeof(wcbuf)/sizeof(wchar_t)),而不是字节数或字符数。这是因为在 Windows 等一些操作系统中,wchar_t 类型并不总是占用固定的字节数,而可能会根据编译器和平台而变化。

6.3 运行结果

7. mbstowcs

7.1 函数说明

函数声明 函数功能
size_t mbsrtowcs(wchar_t *dst, const char **src, size_t len, mbstate_t *ps); 用于将多字节字符序列转换为宽字符序列,并在转换过程中自动更新 mbstate_t 转换状态结构体。

参数:

  • dst: 指向存储结果宽字符序列的缓冲区的指针
  • src : 指向待转换的多字节字符序列的指针的指针
  • len : 缓冲区的最大长度(以宽字符数计)
  • ps : 指向包含转换状态信息的结构体 mbstate_t 的指针

返回值:

  • 如果成功地将多字节字符序列转换为宽字符序列,则该函数返回实际写入缓冲区中的宽字符数,不包括空字符 \0
  • 如果遇到了无效的多字节字符或编码,或者宽字符缓冲区不足,导致转换失败,则该函数返回 (size_t)-1

注意: mbsrtowcs() 函数会自动更新转换状态结构体 mbstate_t,以记录上一次调用的状态并在下一次调用时继续使用。这使得 mbsrtowcs() 函数适用于处理长的、包含部分多字节字符的字符串。它会自动识别和处理多字节字符序列中的部分字符,并等待更多的字节,直到可以完成转换为止。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

int main()
{
// 设置本地化环境
setlocale(LC_ALL, "");

char str[] = u8"你好,世界!";
wchar_t wcbuf[20];
mbstate_t state = {0};

// 将多字节字符序列转换为宽字符序列
size_t ret = mbsrtowcs(wcbuf, (const char**)&str, sizeof(wcbuf)/sizeof(wchar_t), &state);
if (ret == (size_t)-1)
{
printf("Failed to convert multibyte character sequence.\n");
return 1;
}

// 在控制台输出宽字符序列及其长度
wprintf(L"The wide character string is: %ls (%zu characters)\n", wcbuf, ret);

return 0;
}

8. mbtowc

8.1 函数说明

函数声明 函数功能
int mbtowc(wchar_t *restrict pwc, const char *restrict s, size_t n); 用于将一个多字节字符 (Multibyte Character) 转换成一个宽字符 (Wide Character)。

参数:

  • pwc : 指向存储宽字符的指针。
  • s : 指向要转换的多字节字符的指针。
  • n : 要转换的最大字节数。

返回值:

  • 如果转换成功,则返回转换后的宽字符数;
  • 如果遇到无效的多字节字符,则返回 -1
  • 如果传递了空指针,则返回 0

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

int main(void)
{
setlocale(LC_ALL, "");

char mbstr[] = "Hello, world!";
wchar_t wc;
int len = mbtowc(&wc, mbstr, sizeof(mbstr));
if (len > 0) {
wprintf(L"%lc\n", wc);
} else if (len == 0) {
wprintf(L"Empty string.\n");
} else if (len == -1) {
wprintf(L"Invalid multibyte character.\n");
}

return EXIT_SUCCESS;
}

8.3 运行结果

9. memccpy

9.1 函数说明

函数声明 函数功能
void *memccpy(void *restrict dst, const void *restrict src, int c, size_t n); 用于将内存块的内容复制到另一个内存块中,并在指定字符出现时停止复制。
参数:
  • dst : 要复制到的目标内存块的指针
  • src : 要从中复制数据的源内存块的指针
  • c : 指定的字符值
  • n : 要复制的字节数

返回值:

  • 如果源内存块的前 n 个字节中包含字符 c,则返回指向字符 c 后面一个字节的指针;
  • 否则返回 NULL

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char src[] = "Hello, world!";
char dst[20];
memset(dst, 0, sizeof(dst));

char *p = (char*) memccpy(dst, src, 'o', sizeof(src));
if (p) {
printf("'%c' found at index %ld\n", *(p - 1), p - dst - 1);
} else {
printf("'%c' not found\n", 'o');
}

printf("%s\n", dst);

return 0;
}

9.3 运行结果

10. memchr

10.1 函数说明

函数声明 函数功能
void *memchr(const void *s, int c, size_t n); 用于在某一内存块中查找指定字符的位置。

参数:

  • s : 要进行查找的内存块的起始地址
  • c : 要查找的指定字符,以整数形式表示
  • n : 要查找的字节数,即在前 n 个字节中查找指定字符

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char str[] = "Hello, world!";
char ch = 'w';
char *p;

// 在字符串中查找指定字符
p = (char*) memchr(str, ch, strlen(str));
if (p) {
printf("'%c' found at index %ld\n", ch, p - str);
} else {
printf("'%c' not found\n", ch);
}

return EXIT_SUCCESS;
}

在上述程序中,

  • 我们首先定义了一个字符串 str 和要查找的指定字符 ch
  • 然后使用 memchr() 函数查找字符串 str 中是否包含指定字符 ch
  • 最后如果找到了该字符,则输出它的索引位置;否则,输出未找到的提示信息。

10.3 运行结果

11. memcpy

11.1 函数说明

函数声明 函数功能
void *memcpy(void *dest, const void *src, size_t n); 用于将源内存块中的 n 个字节复制到目标内存块中。

参数:

  • dest : 目标内存块的起始地址
  • src : 源内存块的起始地址
  • n : 要复制的字节数

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char src[] = "Hello, world!";
char dst[20];
memset(dst, 0, sizeof(dst));

// 将源字符串复制到目标字符串中
memcpy(dst, src, strlen(src));

printf("%s\n", dst);

return 1;
}

注意: 在使用 memcpy() 函数进行内存复制时,目标内存块必须足够大,以容纳源内存块中的全部内容。否则,复制过程可能会导致访问非法内存空间,从而导致代码异常或崩溃。因此,在进行内存复制时,应该尽量避免超出目标内存块大小的范围。

11.3 运行结果

12. memcmp

12.1 函数说明

函数声明 函数功能
int memcmp(const void *s1, const void *s2, size_t n); 用于比较两个内存块的内容是否相同。

参数:

  • s1 : 要进行比较的第一个内存块的起始地址
  • s2 : 要进行比较的第二个内存块的起始地址
  • n : 要比较的字节数。

注意: memcmp() 函数会逐一比较两个内存块中对应位置上的字节大小,直到找到差异或者比较完全部字节。

  • 如果两个内存块完全相同,则返回值为 0
  • 如果两个内存块不同,则返回值是两个内存块中第一个不同字节处的差值(s1 中该字节的值减去 s2 中该字节的值)。

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char str1[] = "Hello, world!";
char str2[] = "Hello, everyone!";

// 比较两个字符串
int result = memcmp(str1, str2, strlen(str1));
printf("result = %d\n", result);
if (result == 0) {
printf("Strings are equal\n");
} else if (result < 0) {
printf("String '%s' is smaller than string '%s'\n", str1, str2);
} else {
printf("String '%s' is larger than string '%s'\n", str1, str2);
}

return 1;
}

注意: 在比较两个内存块时,应该确保被比较的内存块中包含足够的字节,并且待比较的字节数不超过内存块大小,否则函数可能会出现异常行为。另外,由于返回值是有符号整数类型,因此在比较时应该将其强制转换为无符号整数类型,以避免出现不必要的错误。

12.3 运行结果

13. memmove

13.1 函数说明

函数声明 函数功能
void *memmove(void *dest, const void *src, size_t n); 用于将源内存块中的 n 个字节复制到目标内存块中。与 memcpy() 函数不同的是,memmove() 函数在复制过程中会处理内存块重叠的情况。

参数:

  • dest : 目标内存块的起始地址
  • src : 源内存块的起始地址
  • n : 要复制的字节数。

注意: memmove() 函数会将源内存块中的前 n 个字节复制到目标内存块中,并返回指向目标内存块起始地址的指针。

13.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char str[] = "Hello, world!";
char tmp[20];
memset(tmp, 0, sizeof(tmp));

// 将源字符串复制到目标字符串中(处理重叠的情况)
memmove(tmp, str + 6, strlen(str) - 6);

printf("%s\n", tmp);

return 0;
}

注意: 在使用 memmove() 函数进行内存复制时,目标内存块必须足够大,以容纳源内存块中的全部内容。否则,复制过程可能会导致访问非法内存空间,从而导致代码异常或崩溃。此外,由于 memmove() 函数的处理开销较大,因此在不涉及内存块重叠时,应该尽量使用 memcpy() 函数以提高效率。

13.3 运行结果

14. memset,memset_s

14.1 函数说明

函数声明 函数功能
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 参数:

  • s : 要进行设置的内存块的起始地址
  • c : 要设置的值,以整数形式表示
  • n : 要设置的字节数

memset_s 参数:

  • s : 要进行设置的内存块的起始地址
  • smax : 目标内存块的大小
  • c : 要设置的值,以整数形式表示
  • n : 要设置的字节数

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char str[21] = {'\0'};
memset(str, 'A', sizeof(str) - 1);
printf("%s\n", str);
return 0;
}

14.3 运行结果

参考

  1. [API Reference Document]