1. C中可变参数函数作为函数参数:
void media_debug_set_handler(struct media_device *media, void (*debug_handler)(void *, ...), void *debug_priv) 调用: media_debug_set_handler(media, (void (*)(void *, ...))fprintf, stdout);
2.可变参数函数
gstcaps.c GstCaps *gst_caps_new_full (GstStructure * struct1, ...) { GstCaps *caps; va_list var_args; va_start (var_args, struct1); caps = gst_caps_new_full_valist (struct1, var_args); va_end (var_args); return caps; } GstCaps * gst_caps_new_full_valist (GstStructure * structure, va_list var_args) { GstCaps *caps; caps = gst_caps_new_empty (); while (structure) { gst_caps_append_structure_unchecked (caps, structure); structure = va_arg (var_args, GstStructure *); } return caps; }
3.offsetof实现
#include <stddef.h>中 #define offsetof(TYPE, MEMBER) ((int)&((TYPE *)0)->MEMBER)
疑问:为什么自己同样实现报将指针强制类型转换为int,使用头文件中的怎么没有呢 ?
4.C的精髓
#include <stdio.h> #include <stdlib.h> void getArray(long *p) { int i, j, n = 0; int *p1 = malloc(256); for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { p1[n++] = n; } } *p = (long)p1; } void printArray(void **p) { int i, j; int (*p1)[5] = (int (*)[])p; //int **p1 = (int **)p; //oops,for different deference protocoal for (i = 0; i < 5; i++) { for (j = 0; j < 5; j++) { printf("[%d %d]", p1[i][j], *(*(p1+i)+j)); //array pointer also can use ** to deference } printf(" "); } } int main() { int **p = NULL; getArray((long *)&p); //三级指针可以强制转换成一级指针进行传参,印证只有值传递 printArray((void **)p); free((void *)p); return 0; }
5.GNU扩展
int main() { int i; char a[10] = {[0 ... 5] = 10}; for (i = 0; i < 10; i++) { printf("a[%d] = %d ", i, a[i]); } return 0; }
6.errno
errno 是记录系统的最后一次错误代码,错误代码定义在Linux内核的errno-base.h中。errno是一个int型的值,在errno.h中定义。
当linux C api函数发生异常时, 一般会将errno变量(需include errno.h)赋一个整数值, 不同的值表示不同的含义,可以通过查看该
值推测出错的原因。
注意errno记录的是最后一次出错的错误代码,感兴趣的错误代码可能被最新的错误覆盖!
#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <errno.h> void main() { printf("errno = %d ", errno); // errno=0 // chmod 444 tmp.txt int fd = open("tmp.txt", O_RDWR); //此时errno=13: Permission denied if (fd < 0) { // no log.txt fd = open("log.txt", O_RDWR); printf("error: %s ", strerror(errno)); //由于log.txt不存在,此处报的是No such file or directory } }
7. C中左右两边都可以的强制类型转换
#include <stdio.h> #include <stdlib.h> void* get_mem(){ return malloc(8); } void main() { float *p1; int *p2, *p3; p1 = (float*)get_mem(); printf("p1=%p ", p1); p3 = (int*)p1; //在右边进行强制类型转换 *(float**)&p2 = p1; //在左边进行强制类型转换 printf("p2=%p ", p2); printf("p3=%p ", p3); printf("Hello World "); free(p1); }
&p2是一个常量,(float**)指定为地址,解引用为向此常量地址存储空间中写入值,此地址刚好就是p2指针的存储空间。