C经典案例

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
    }
}
View Code

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指针的存储空间。

原文地址:https://www.cnblogs.com/hellokitty2/p/9070078.html