Head First C (后半部分)读书笔记

来源:互联网 发布:在数据库的增删改查 编辑:程序博客网 时间:2024/05/16 07:30

后半部分大部分代码要在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上的MinGWgcc -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可以简写为:

%: %.cgcc $^ -o $@# $^代表依赖的项(.c文件)。# $@代表目标的名字。

POSIX定义了一个宏PTHREAD_MUTEX_INITIALIZER来静态初始化互斥锁,如:

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

设计高效的多线程程序的一个方法,就是减少线程间需要访问的共享数据的数量。

0 0