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

  • 相关阅读:
    linux下简单线程池实现
    mongodb日志文件切换
    SQL Server中如何统计数据库中所有用户表所占空间大小?
    Windows 2008 R2 + IIS7.5客户端证书认证问题?
    mongodb Replica Sets +Sharding高可用集群搭建(含认证)
    读书笔记linux vfs
    SQL Server 常用性能分析语句
    CentOS6.2下fastDFS的完整安装和配置步骤
    改进jquery.tablesorter.js 支持中文表格排序
    Sage CRM升级注意事项三
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/9070078.html
Copyright © 2020-2023  润新知