zoukankan      html  css  js  c++  java
  • GNU C语法扩展(10)

    6217760-e609897bd82c4891.png

    要研究LINUX内核,C语言是基础中的基础,但是LINUX并不是完全的标准C,而是对标准C做了很多扩展,这些扩展特性对于我们分析内核有着很重要的作用,下面做些总结性的工作。

    10、内建函数

    GNU C提供了大量的内建函数,其中很多是标准C库函数的内建版本,例如memcpy,它们与对应的C库函数功能相同,本文不讨论这类函数,其他内建函数的名字通常以__builtin开始。

    • 内建函数__builtin_return_address(LEVEL)返回当前函数或其调用者的返回地址,参数LEVEL指定调用栈的级数,如0表示当前函数的返回地址,1表示当前函数调用者的返回地址,依此类推。例
      如:
    //kernel/sched.c
    printk(KERN_ERR "schedule_timeout: wrong timeout" "value %lx from %p
    ", timeout, __builtin_return_address(0));
    
    • 内建函数__builtin_constant_p(EXP)用于判断一个值是否为编译时常数,如果参数EXP的值是常数,函数返回1,否则返回0。
    //include /asm-i386/bitops.h
    #define test_bit(nr,addr)/
        (__builtin_constant_p(nr)?/
        constant_test_bit( (nr),(addr) ):/
        variable_test_bit( (nr),(addr) ) )
    

    很多计算或操作在参数为常数时有更优化的实现,在GNUC中用上面的方法可以根据参数是否为常数,只编译常数版本或非常数版本,这样既不失通用性,又能在参数是常数时编译出最优化的代码。

    • 内建函数__builtin_expect(EXP, C)用于为编译器提供分支预测信息,其返回值是整数表达式EXP的值,C的值必须是编译时常数。例如:
    //include /linux/compiler.h
    #define likely(x) __builtin_expect((x),1)
    #define unlikely(x) __builtin_expect((x),0)
    
    //kernel/sched.c
    if( unlikely(in_interrupt()) ){
        printk("Schedulingininterrupt/n");
        BUG();
    }
    

    这个内建函数的语义是EXP的预期值是C,编译器可以根据这个信息适当地重排语句块的顺序,使程序在预期的情况下有更高的执行效率。上面的例子表示处于中断上下文是很少发生的,第6-7行的目标码可能会放在较远的位置,以保证经常执行的目标码更紧凑。
    若不想使用GNUC扩展,那么只需要在gcc参数后面加上-ansi-pedantic即可,使用上述参数后,所有GNCC扩展语法部分将会有编译警报。

    更多知识:
    点击关注专题:嵌入式Linux & ARM

    或浏览器打开:https://www.jianshu.com/c/42d33cadb1c1

    或扫描二维码:

    6217760-e6bba06e005d8fe7.jpg

  • 相关阅读:
    张拥军:解码商品期货投资实战应用 2011年06月02日
    罗小奔:谈一下最近商品期货套利的几个机会
    罗小奔:商品期货套利当前之我见
    leetcode -- Binary Tree Preorder Traversal
    leetcode -- Linked List Cycle II
    leetcode -- Linked List Cycle
    [转载]2014年10月26完美世界校招两道java题
    [转载]SQL truncate 、delete与drop区别
    [转载]会引起全表扫描的几种SQL
    [转载]Linux I/O 调度方法
  • 原文地址:https://www.cnblogs.com/leon1124/p/14039784.html
Copyright © 2011-2022 走看看