zoukankan      html  css  js  c++  java
  • C语言学习笔记_C语言宏定义与预处理

    C语言学习笔记_C语言宏定义与预处理

    由源码到可执行程序的过程

    1. 源码;
    2. 预处理过的.i源文件
    3. 汇编文件.s
    4. 目标文件.o
    5. elf可执行程序

    条件编译

    // 定义XXX
    #define XXX
    
    // 这种方式直接判定XXX是否被定义
    #ifdef XXX
    #else
    #endif
    
    // 这种方式判断条件是否为真
    #if (1)
    #else
    #endif
    

    宏定义

    宏定义在编译器的预处理阶段会被直接替换;

    替换的过程是递归的,如下:

    #define N 10
    #define M N
    
    // 相当于int a[10];
    int a[M];
    

    当宏定义带参数的时候,擅用括号,避免替换的时候出现歧义,如获取最大值的宏:

    #define MAX(a, b)	((a) > (b) ? (a) : (b))
    
    int max(int a, int b) {
        return a>b?a:b;
    }
    
    int a = 1, b = 2;
    int max = MAX(a*3, b);
    

    这里例子可能举得不是很好,但是在某些时候不加括号会使得替换后引起歧义,导致出错;

    带参宏和带参函数有如下差别:

    1. 宏定义原地展开,因此没有调用开销;而函数是跳转执行在返回;
    2. 宏定义不会检查参数的类型,返回值也不会附带类型,而函数有明确的参数类型和返回值类型;当调用函数时编译器会做参数的静态类型检查;

    另外一个例子,利用宏定义得到一年有多少秒:

    #define SER_PER_YEAR	(365*24*60*60UL)
    

    注意:

    在程序中的数字默认为int类型,而秒数正好超过了int的范围;

    所以在数字后面加上UL使得数组变成无符号long;

    另外一个例子,利用条件宏设置debug

    // 定义DEBUG
    #define DEBUG
    
    // 使用undef消除对DEBUG的定义
    #undef DEBUG
    
    #ifdef DEBUG
    #define debug(x) printf(x)
    #else
    #define debug(x)
    #endif
    
    
    debug("hello world.
    ");
    

    通过定义DEBUG,使得debug可以用于打印信息,如果不需要了可以注释DEBUG的定义,或者使用undef,使得消除调试信息更方便。

    使用undef时,前面若没有定义过,将会无视此语句;

    内联函数

    在宏定义中讲到,带参宏和函数的区别是:带参宏开销小但是不做类型检查,函数有调用开销但是会做类型检查;

    而内敛函数具有上述两者的优点,其没有调用开销且会做类型检查,只需要在函数前加inline

    inline void printInfo() {
    	printf("hello world.
    ");
    }
    
  • 相关阅读:
    c# webapi无法获取Session值问题解决
    深入理解java虚拟机之自动内存管理机制笔记
    数据结构总结1
    疯人院之语言、编码、计算机

    集线器/交换机
    什么是DOM?DOM和JavaScript的关系 [web开发]
    JSON轻量级的数据交换格式
    天问宇宙学第一课
    C++基础知识
  • 原文地址:https://www.cnblogs.com/sakurapiggy/p/13296386.html
Copyright © 2011-2022 走看看