zoukankan      html  css  js  c++  java
  • c 预处理的宏定义

    概念

    以“#”号开头的都是预处理命令

    例如 #include <stdio.h>宏定义

    宏定义
    无参数的宏名后不带参数
    # 表示这是一条预处理命令, define 为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数,表达式、格式串等

    举例:

    #define PI 3.1415926

    作用:

    就是用指定标识符PI来代替数3.1415926
    对源程序作编译时, 将先由预处理程序进行宏代换,
    即用3.1415926表达式去置换所有的宏名PI, 然后编译

    #include <stdio.h>
    
    # define PI 3.1415
    
    
    int main(int argc, char const *argv[]) {
      printf("%f
    ", PI);
      return 0;
    }
    View Code

    注意: 

    1. 预处理程序对宏定义不做任何检查,如果有错误,只能在编译已被宏展开后的源程序是发现

    2. 宏定义不是说明或语句,在行末不必加分好,如加上分好则连分号也一起置换 容易出错的地方

    3. 宏定义必须写在函数之外, 其作用域为宏定义命令起到源程序结束。如要终止其作用域可
    使用# undef命令

    4. 宏定义用双引号括起来的都是常量字符串 例如“PI” 则打印PI

    5. 宏定义允许嵌套, 在宏定义的字符串中,可以使用已定义的宏名。在宏展开时由预处理程序层层代换。

    6. 习惯上宏定义用大写字母表示, 以便区分

          #include <stdio.h>
    
          # define PI 3.1415
          # define S PI*r*r
    
          int main(int argc, char const *argv[]) {
            double s;
            int r;
            scanf("%d", &r);
            s = S;
            printf("%d
    ", s);
            return 0;
          }
    View Code

    7. 可用宏定义表示数据类型, 是书写方便

    # define INTEGER int 

    8. 对“输出格式”作宏定义, 可以缩减书写麻烦

    #include <stdio.h>
    
    # define P printf
    # define D "%d
    "
    
    int main(int argc, char const *argv[]) 
    {
        p(D, 1);
      
    }

    define 和typeof的区别

    宏定义      只是简单的字符串代换, 是预处理完成的。
    typedef    是在编译时处理的, 它不是作简单的代换, 而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。
    typedef    相当于类型重命名

    #include <stdio.h>
    
    #define  PIN1 char*  // -->通常我们用define定义数值
    typedef char* PIN2;  // -->通常我们用typedef定义数据类型和结构
    
    int main(int argc, char const *argv[]) {
    
      PIN1 x, y; // char* x, y;也就是   char *x, y
      PIN2 a, b; // char* a, b;   char *a, *b;
      printf("%d %d
    ", sizeof(x), sizeof(y));
      printf("%d %d
    ", sizeof(a), sizeof(b));
      //结果:
      // 8 1
      //8  8 
    }

    带参数宏定义

    c语言允许宏带有参数, 在宏定义中的参数成为形式参数, 在宏调用中的参数成为实际参数。

    对带参数的红,在调用中, 不仅要展开,而且要用实参去代替形参

    带参宏定义的一般形式为:

    # define 宏名(形参表) 字符串
    带参宏调用的一般形式为: 宏名(实参表)

    例如:

    	#define M(y) y*y+3*y /*宏定义*/
    
    	。。
    	k=M(5);   /*宏调用*/
    	相当于k = 5*5 + 3*5  会直接替换,没有预处理的过程
    

      

    看例子

    #include <stdio.h>
    
    #define MAX(a, b) (a, b)?a:b
    
    int main(int argc, char const *argv[])
    {
        int x, y, max;
    
        scanf("%d %d", &x, &y);
        max = MAX(x, y);
        printf("%d
    ", max);
        return 0;
    }

    注意:

    首先win编程里面都是宏定义

    1. 带参宏定义中,宏名和形参表之间不能有空格出现
    例如:

    正确:
    #define MAX(a, b) (a>b)?a:b
    错误:
    #define MAX (a, b) (a>b)?a:b

    2. 在带参宏定义中,形式参数不分配内存单元, 因此不必作类型定义。
    而宏调用中的实参有具体的值。要用他们去代换形参, 因此必须作类型说明


    3. 在宏定义中的形参是标识符, 而宏调用中的实参可以是表达式


    4. 在宏定义中, 字符串内的形参通常要用括号括起来以避免出错。
    例如 # define M(y) (y)^(y)表达式的y都用括号括起来, 因此结果是正确的。
    如果去掉括号, 把程序改成一下形式,那么程序的结果不是你想要的结果

    注意:

    #define S(y) (y)*(y)
    
    .....
    sq = 160 / S(3) //等于160 / (y)*(y)
    需要更改成 #define S(y) ((y)*(y))

    5. 带参宏和带参函数很相似, 但有本质上的不同, 除上面已谈到的各点外,
    把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。

    稍等例子,明天测试


    6. 宏定义也可以定义多个语句, 在宏调用时, 把这些语句又代换到源程序内
    #include <string.h>
    # define S(s1, s2) strcat(s1, s2) //strcat 类似连接,或合并

    宏定义的if

    条件编译三种形式:
    1. #ifdef 标识符
        程序段1
      #else
        程序段2
      #endif

    2. #ifndef 标识符
        程序段1
      #else
        程序段2
      #endif


    3.#if 常量表达式
        程序段1
      #else
        程序段2
      #endif

  • 相关阅读:
    ES6常用语法
    nodejs中exports与module.exports的区别
    CSS animation动画
    CSS user-select文本是否可复制
    VUE 滚动插件(better-scroll)
    VUE 父组件与子组件交互
    CSS div内文字显示两行,超出部分省略号显示
    linux下使用tar命令
    linux fdisk命令使用
    关于SUID、SGID、Sticky
  • 原文地址:https://www.cnblogs.com/renfanzi/p/6765052.html
Copyright © 2011-2022 走看看