后半部分大部分代码要在Linux系统下运行,系统切换麻烦,也就没怎么仔细看。
void qsort(void *array, size_t length, size_t item_size, int (*compare)(const void *, const void *));
- array: 待排序数组指针。
- length: 数组元素个数。
- item_size: 数组中每个元素的占用字节数。
- compare: 用来比较数组中两项数据大小的函数指针。
头文件stdlib.h。
compare((void *)&elem1, (void *)&elem2);
compare()函数返回值 | 描述 |
---|---|
<0 | elem1将被排在elem2前面 |
0 | elem1等于elem2 |
>0 | elem1将被排在elem2后面 |
也就是说,函数的返回值决定了数组的排序方式。
各类比较函数的参考写法: qsort函数用法
类似的有bsearch()函数: C语言中用bsearch()实现查找操作
int scanf( const char *format [,argument]... );
其中的format
可以是一个或多个{%[*] [width] [{h | l | I64 | L}]type | ' ' | '\t' | '\n' | 非%符号}
。
*
亦可用于格式中, 如%*d
和%*s
。加了*
表示跳过此数据不读入。width
表示读取宽度。{h | l | I64 | L}
表示参数的size,通常h表示单字节size,I表示2字节size,L表示4字节size(double例外),l64表示8字节size。type
就是%s
、%d
之类的。- 特别的:
%*[width] [{h | l | I64 | L}]type
表示满足该条件的将被过滤掉,不会向目标参数中写入值。 - 支持集合操作:
%[a-z]
表示匹配a到z中任意字符,贪婪性(尽可能多地匹配)。%[aB']
匹配a、B、’中的一员,贪婪性。%[^a]
匹配非a的任意字符,贪婪性。
以上内容来自:scanf(“%[^\n]”,a); 谁来详细解释下~,里面有更详细的例子。
exec()函数通过运行其他程序来替换当前进程。
大致可以分为两组:列表函数 和 数组函数。
- 列表函数以参数列表的形式接受命令行参数。
execl("/home/flynn/clu", "/home/flynn/clu", "paranoids", "contract", NULL);
//execl = 参数列表(List)
execlp("clu", "clu", "paranoids", "contract", NULL);
//execlp = 参数列表(List) + 在PATH中查找程序
execle("/home/flynn/clu", "/home/flynn/clu", "paranoids", "contract", NULL, env_vars);
//env_vars是一个字符串数组,里面放了环境变量,如:"POWER=4"、"SPEED=17"、"PORT=OPEN"等。
//execle = 参数列表(List) + 环境变量(Environment)。
- 数组函数已经把命令行参数保存在了数组中。
ececv("/home/flynn/clu", my_args);
//my_args是一个字符串数组,里面放了命令行参数。
//execv = 参数数组或参数向量(vector)。
execvp("clu", my_args);
//execvp = 参数数组或参数向量(vector) + 在PATH中查找。
execve("/home/flynn/clu", my_args, env_vars);
//execve = 参数数组或参数向量(vector) + 环境变量(Environment)。
可变参数函数
#include <stdarg.h>
//所有处理可变参数函数的代码都在stdarg.h中。
void print_ints(int args, ...){
//返回值类型和函数名和一般函数一样。参数列表至少有一个参数,省略号表示可变参数。
va_list ap;
//va_list用来保存传给函数的其他参数。
va_start(ap, args);
//va_start表示可变参数从哪里开始。传入的是最后一个普通参数。
int i;
for( i = 0; i < args; i++){
//这里是使用了普通参数args来保存变量的数目,只是一般使用,并非特定要求。
printf("argument: %i\n", va_arg(ap, int));
//va_arg从va_list中读取参数,参数类型为int。
}
va_end(ap);
//va_end宏销毁va_list。
}
print_ints(3, 79, 101, 32); //将打印79,101和32。
print_ints(1, 79); //将打印79。
创建函数的同时也创建了一个同名函数指针(常量),指针中保存了函数的地址。当调用函数时,使用的是函数指针。
函数指针数组:函数返回类型 (*指针变量)(函数参数类型),如:
void (*funcptr[])(char *, int *) = {func1, func2, func3};
文件描述符是一个数字,它表示一条数据流。文件描述符描述的不一定是文件。
文件描述符 | 数据流连向 |
---|---|
0 (标准输入stdin) | 键盘 |
1 (标准输出stdout) | 屏幕 |
2 (标准错误stderr) | 屏幕 |
pipe()函数创建管道,打开两条数据流。
int fd[2];
if(pipe(fd) == -1){
printf("Can't create the pipe!\n");
}
pipe()函数创建的两个描述符:fd[1]
用来向管道写数据,fd[0]
用来从管道读数据。
close(fd[0]); //关闭管道读取端
dup2(fd[1], 1); //将管道写入端连到标准输出
//这样就可以将标准输出写入管道
dup2(fd[0], 0); //将管道读取端连到标准输入
close(fd[1]); //关闭管道写入端
//这样就可以读取管道写入标准输入
创建静态库(Static library / Statically-linked library)
ar -rcs libarchive.a file0.o file1.o
# 存档命名为libXXX.a。
# r表示如果.a文件则更新它。
# c表示创建存档时不显示反馈信息。
# s表示ar要在.a文件开头建立索引。
创建动态链接库(Dynamic-link library / DLL)
gcc -shared hfcal.o -o C:\libs\hfcal.dll # Windows上的MinGW
gcc -shared hfcal.o -o /libs/libhfcal.dll.a # Windows上的Cygwin
# 在Linux/Unix上叫共享目标文件,后缀名为.so。
# 在Mac上叫动态库,后缀名为.dylib。
gcc
-I./include
包含其他头文件路径 -L./libs
包含其他库文件路径
关于Makefile
不存在makefile文件时,直接make xxx
会使用隐式规则cc xxx.c -o xxx
。
当有多个文件编译方式相同时,makefile可以简写为:
%: %.c
gcc $^ -o $@
# $^代表依赖的项(.c文件)。
# $@代表目标的名字。
POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER
来静态初始化互斥锁,如:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
设计高效的多线程程序的一个方法,就是减少线程间需要访问的共享数据的数量。