`
JavaFans
  • 浏览: 88824 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

[转载]C语言宏定义总结

阅读更多
C语言宏定义总结

转自:http://topcool99.ycool.com/post.1797687.html

宏定义了一个代表特定内容的标识符。
预处理过程会把源代码中出现的宏标识符替换成宏定义时的值。
宏最常见的用法是定义代表某个值的全局符号。
宏的第二种用法是定义带参数的宏,这样的宏可以象函数一样被调用,但它是在调用语句处展开宏,并用调用时的实际参数来代替定义中的形式参数。

  1.#define指令
    #define MAX_NUM 10
    int array[MAX_NUM];
    for(i=0;i<MAX_NUM;i++)  /*……*/
    #define VERSION "Version 1.0 Copyright(c) 2003"

  2.带参数的#define指令
   #define IS_EVEN(n)   ((n)%2==0)
   #define MAX(x,y)     ((x)>(y) ? (x) :(y))
    #define Cube(x) (x)*(x)*(x)

    可以是任何数字表达式甚至函数调用来代替参数x。
  3.#运算符
    #的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个双引号。例如:
        #define _STR(s)     #s 
        #define WARN_IF(EXP)    \
        do{ if (EXP)    \
            fprintf(stderr, "Warning: " #EXP "\n"); }   \
        while(0)

        那么实际使用中会出现下面所示的替换过程:
        WARN_IF (divider == 0);

     被替换为
        do {
            if (divider == 0)
          fprintf(stderr, "Warning" "divider == 0" "\n");
        } while(0);

这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。

再例如下面的例子:
     #define  FILL(a)   {a, #a}

     enum IDD{OPEN, CLOSE}; 
     typedef struct MSG{ 
        IDD id; 
        const char * msg; 
     }MSG;

     MSG _msg[] = {FILL(OPEN), FILL(CLOSE)}; 

     相当于:
       MSG _msg[] = {{OPEN, "OPEN"}, 
                     {CLOSE, "CLOSE"}}; 


  4.##运算符
    ##运算符用于把参数连接到一起。
预处理程序把出现在##两侧的参数合并成一个符号。
看下面的例子:
            #define NUM(a,b,c) a##b##c
            #define STR(a,b,c) a##b##c

            main()
            {
                printf("%d\n",NUM(1,2,3));
                printf("%s\n",STR("aa","bb","cc"));
            }

        最后程序的输出为:
                 123
                 aabbcc
再看下面的例子:
 struct command
    {
     char * name;
     void (*function) (void);
    };

    #define COMMAND(NAME) { NAME, NAME ## _command }

   // 然后你就用一些预先定义好的命令来方便的初始化一个command结构的数组了:
    struct command commands[] = {
     COMMAND(quit),
     COMMAND(help),
     ...
    }

    COMMAND宏在这里充当一个代码生成器的作用,这样可以在一定程度上减少代码密度,间接地也可以减少不留心所造成的错误。我们还可以n个##符号连接 n+1个Token。比如:
 
    #define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d

    typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
    // 这里这个语句将展开为:
    // typedef struct _record_type name_company_position_salary;

  5.特殊的宏
    #error指令将使编译器显示一条错误信息,然后停止编译。
    #line指令可以改变编译器用来指出警告和错误信息的文件号和行号。
    #pragma指令没有正式的定义。编译器可以自定义其用途。典型的用法是禁止或允许某些烦人的警告信息。
...在C宏中称为Variadic Macro,也就是变参宏。

  Compiled on Dec 23 1996 at 22:18:48

 6.预定义宏
  __LINE__   被编译的文件的行数
  __FILE__   被编译的文件的名字
  __DATE__   编译的日期(格式"Mmm dd yyyy")
  __TIME__   编译的时间(格式"hh:mm:ss")
  __STDC__   如果编译器接受标准C,那么值为1

  printf("Compiled on %s at %s\n", __DATE__, __TIME__);

  每次程序开始执行,程序都会显示,用于确认版本:
    Compiled on Dec 23 1996 at 22:18:48
    下面的宏可以帮助我们查明错误的根源:
    #define CHECK_ZERO(divisor)  \
       if (divisor == 0)  \
       printf("*** Attempt to divide by zero on line %d  "  \
       "of file %s  ***\n",__LINE__, __FILE__)

     CHECK_ZERO宏应该在除法运算前被调用:
        CHECK_ZERO(j);k = i / j;

    如果j是0,会显示出如下形式的信息:
    *** Attempt to divide by zero on line 9 of file FOO.c ***
    通用的、用于错误检测的宏——assert宏;

  7.注意
    宏名和参数的括号间不能有空格;
宏替换只作替换,不做计算,不做表达式求解;
函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存;
函数只有一个返回值,利用宏则可以设法得到多个值;
宏展开使源程序变长,函数调用不会;
宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值);
使用条件编译可以使目标程序变小,运行时间变短;
预编译使问题或算法的解决方案增多,有助于我们选择合适的解决方案。

-------------声明,可能部分资源来源于网络,仅为了给大家的学习提供方便,如怀疑有侵权行为,请和我联系,我将立即删除。
分享到:
评论

相关推荐

    C语言宏定义技巧,很详细

    C语言宏定义技巧 C语言宏定义技巧C语言宏定义技巧C语言宏定义技巧

    c语言宏定义技巧,常用宏定义方法

    ### C语言宏定义技巧详解 #### 一、引言 在C语言编程中,宏定义是一种非常实用且强大的工具,它能够帮助程序员更好地组织代码、提高代码的可读性和可维护性。通过合理地使用宏定义,我们不仅能够避免一些常见的...

    c语言宏定义技巧(常用宏定义)

    写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等。

    C语言宏定义用法大全

    在C语言中,宏定义(Macro Definition)是一种预处理指令,用于在程序编译之前对源代码进行文本替换。它由预处理程序在编译之前处理,不占用运行时的任何资源。宏定义可以定义常量,也可以定义带参数的宏,与函数有...

    C语言宏定义技巧

    C语言宏定义技巧(常用宏定义)

    巧用C语言宏定义实现自动注释调试代码

    总结来说,C语言中的宏定义在调试代码时能发挥以下作用: 1. 条件编译:根据宏定义的状态决定是否执行特定代码。 2. 自动注释:通过宏定义可以快速开关调试信息,简化代码维护。 3. 提供位置信息:利用预定义宏如`__...

    几个C语言常用宏定义技巧

    几个C语言常用宏定义技巧,入门级

    C语言宏定义技巧,写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性 等等

    "C语言宏定义技巧" C语言宏定义技巧是编写高质量C语言程序不可或缺的一部分。使用宏定义可以防止出错,提高可移植性、可读性和方便性等等。下面详细介绍C语言宏定义技巧的应用场景和实现方法。 1. 防止头文件被...

    C语言宏定义##连接符和#符的使用

    ### C语言宏定义中的##连接符和#符详解 在C语言编程中,宏定义是一种常用的预处理功能,它能够帮助开发者实现代码的简化、复用以及特定逻辑的快速构建。本文将详细介绍C语言宏定义中两个特殊符号的使用:连接符`##`...

    c语言宏定义详解

    更加清楚明了得学懂c语言,明确宏定义在c中是怎样表示的,让大家少走弯路。

    C语言宏定义使用技巧.pdf

    总结来说,C语言宏定义使用技巧包括数据类型定义、计算和操作函数、位操作、内存地址操作、条件编译、特定数值计算和字符处理等。通过合理地使用宏定义,可以提高代码的可读性、可维护性以及性能。然而,宏定义的...

    C语言宏定义技巧大全

    "C语言宏定义技巧大全" 本资源主要介绍了C语言宏定义的各种技巧,旨在帮助开发者养成良好的宏编程习惯,从而提高代码的可读性、可移植性和方便性。 一、防止重复包含 在C语言中,头文件的重复包含是一个常见的问题...

    C语言宏定义技巧.pdf

    标题《C语言宏定义技巧.pdf》表明本文档主要涉及C语言中宏定义的使用技巧。宏定义是C语言中一种预处理指令,通过它可以定义一些可以替换的值或代码片段,这有助于提高代码的可读性、可维护性和可移植性。在描述中...

    AVR单片机C语言宏定义技巧

    使用C语言编写AVR单片机程序时,掌握宏定义的技巧至关重要,因为宏定义可以提升代码的可读性、可维护性和可移植性。以下是一些常见的宏定义及其用途: 1. **防止头文件重复包含**: 使用`#ifndef`、`#define`和`#...

    C语言宏定义技巧(常用宏定义)

    以下是一些常见的C语言宏定义技巧: 1. **防止头文件重复包含**: 使用`#ifndef`、`#define`、`#endif`三元组可以避免头文件在多个地方被包含时导致的编译错误。例如,当头文件`comdef.h`被包含时,如果已经定义了...

    c语言宏定义详解[参考].pdf

    C语言宏定义详解 C语言宏定义是C语言编程中的一种重要技术,用于在编译期对代码进行预处理和替换。本文将对C语言宏定义进行详细的解释,并提供一些常用的宏定义示例。 1. 宏定义的基本概念 宏定义是C语言编程中的...

    C语言常用宏定义技巧

    本文将详细介绍一些常用的C语言宏定义技巧,并通过具体示例进行说明。 #### 二、防止头文件重复包含 为了避免在多个源文件中多次包含同一个头文件导致的编译错误,通常会采用条件预处理指令来避免重复包含问题。...

Global site tag (gtag.js) - Google Analytics