C经典案例

时间:2023-12-27 09:43:37

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 = ;
int *p1 = malloc(); for (i = ; i < ; i++) {
for (j = ; j < ; j++) {
p1[n++] = n;
}
} *p = (long)p1;
} void printArray(void **p) {
int i, j;
int (*p1)[] = (int (*)[])p;
//int **p1 = (int **)p; //oops,for different deference protocoal for (i = ; i < ; i++) {
for (j = ; j < ; j++) {
printf("[%d %d]", p1[i][j], *(*(p1+i)+j)); //array pointer also can use ** to deference
}
printf("\n");
}
} int main() {
int **p = NULL; getArray((long *)&p); //三级指针可以强制转换成一级指针进行传参,印证只有值传递 printArray((void **)p); free((void *)p); return ;
}

5.GNU扩展

int main() {
int i;
char a[] = {[ ... ] = }; for (i = ; i < ; i++) {
printf("a[%d] = %d\n", i, a[i]);
} return ;
}

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\n", errno); // errno=0
// chmod 444 tmp.txt
int fd = open("tmp.txt", O_RDWR); //此时errno=13: Permission denied
if (fd < ) {
// no log.txt
fd = open("log.txt", O_RDWR);
printf("error: %s\n", strerror(errno)); //由于log.txt不存在,此处报的是No such file or directory
}
}

7. C中左右两边都可以的强制类型转换

#include <stdio.h>
#include <stdlib.h> void* get_mem(){
return malloc();
} void main()
{
float *p1;
int *p2, *p3;
p1 = (float*)get_mem();
printf("p1=%p\n", p1);
p3 = (int*)p1; //在右边进行强制类型转换
*(float**)&p2 = p1; //在左边进行强制类型转换
printf("p2=%p\n", p2);
printf("p3=%p\n", p3);
printf("Hello World\n");
free(p1);
}

&p2是一个常量,(float**)指定为地址,解引用为向此常量地址存储空间中写入值,此地址刚好就是p2指针的存储空间。