zoukankan      html  css  js  c++  java
  • 34 函数与宏分析

    1 函数与宏

    • 宏 or 函数?

      #define RESET(p,len)	
          while(len > 0)		
              ((char*)p)[--len] == 0
      
      void reset(void* p,int len)
      {
          while(len > 0)
          {
              ((char*)p)[--len] = 0;
          }
      }
      
    • 宏与函数的区别

      • 宏是由预处理器直接替换展开的,编译器不知道宏的存在
      • 函数是由编译器直接编译的实体,调用行为由编译器决定
      • 多次使用宏会导致最终可执行程序的体积增大
      • 函数是跳转执行的,内存中只有一份函数体存在
      • 宏的效率比函数要高,因为是直接展开,无调用开销
      • 函数调用时会创建活动记录,效率不如宏
    • 示例:函数与宏

      • Demo:将数组中的每个字节重置为 0
        #include <stdio.h>
        
        #define RESET(p, len)          
            while( len > 0 )           
                ((char*)p)[--len] = 0
        
        void reset(void* p, int len)
        {
            while( len > 0 ) 
                ((char*)p)[--len] = 0;
        }
        
        int main()
        {
            int array1[] = {1, 2, 3, 4, 5};
            int array2[] = {1, 2, 3, 4, 5};
            int len1 = sizeof(array1);  // array1数组的字节数:20,≠5
            int len2 = sizeof(array2);  // array2数组的字节数:20,≠5
            int i = 0;
            
            RESET(array1,len1);
            for(i = 0; i < 5; i++)
            {
                printf("array1[%d] = %d
      ", //i, array1[i]);
            }
            
            reset(array2,len2);
            for(i = 0; i < 5; i++)
            {
                printf("array2[%d] = %d
      ", i, array2[i]);
            }
            
            return 0;
        }
      
      • 编译运行

        array1[0] = 0
        array1[1] = 0
        array1[2] = 0
        array1[3] = 0
        array1[4] = 0
        array2[0] = 0
        array2[1] = 0
        array2[2] = 0
        array2[3] = 0
        array2[4] = 0
        
    • 宏与函数的选择

      • 可以用函数完成的功能绝对不用宏

      • 宏的定义中不能出现递归定义

      • 宏的效率比函数稍高,但是其副作用巨大

      • 宏是文本替换,参数无法进行类型检查

        • Demo1:错误使用宏时

          #include <stdio.h>
          
          #define RESET(p, len)          
              while( len > 0 )           
                  ((char*)p)[--len] = 0
          
          void reset(void* p, int len)
          {
              while( len > 0 ) 
                  ((char*)p)[--len] = 0;
          }
          
          int main()
          {
              int array[] = {1, 2, 3, 4, 5};
              int len = sizeof(array);
              int i = 0;
              
              RESET(6,len);
              for(i = 0; i < 5; i++)
              {
                  printf("array[%d] = %d
          ", //i, array[i]);
              }
              
              return 0;
          }
          
          • 编译不报错,运行错误
          段错误
          
          • Demo2:错误调用函数时
          #include <stdio.h>
          
          #define RESET(p, len)          
              while( len > 0 )           
                  ((char*)p)[--len] = 0
          
          void reset(void* p, int len)
          {
              while( len > 0 ) 
                  ((char*)p)[--len] = 0;
          }
          
          int main()
          {
              int array[] = {1, 2, 3, 4, 5};
              int len = sizeof(array);
              int i = 0;
              
              reset(6,len);
              for(i = 0; i < 5; i++)
              {
                  printf("array[%d] = %d
          ", i, array[i]);
              }
              
              return 0;
          }
          
          • 编译时直接报错
          test.c: In function ‘main’:
          test.c:19: warning: passing argument 1 of ‘reset’ makes pointer from integer without a cast
          test.c:7: note: expected ‘void *’ but argument is of type ‘int’
          
    • 示例:宏的副作用

      • Demo

        #include <stdio.h>
        
        #define _ADD_(a, b) a + b
        #define _MUL_(a, b) a * b
        #define _MIN_(a, b) ((a) < (b) ? (a) : (b))
        
        int main()
        {
            int i = 1;
            int j = 10;
            
            printf("%d
        ", _MUL_(_ADD_(1, 2), _ADD_(3, 4)));  //预期:(1 + 2) * ( 3 * 4) => 结果:11
            printf("%d
        ", _MIN_(i++, j));  //预期:1 < 10 ? 1 : 10 => 结果:2
            
            return 0;
        }
        

    3 宏的妙用

    • 用于生成一些常规性的代码

    • 封装函数,加上类型信息

    • 示例:宏的妙用

      • Demo

        #include <stdio.h>
        #include <malloc.h>
        
        //函数封装:加上类型信息
        #define MALLOC(type, x)   (type*)malloc(sizeof(type)*x)
        //函数封装:释放指针指向的动态内存,并立即将产生的野指针赋值为空
        #define FREE(p)           (free(p), p=NULL)
        
        //封装打印函数
        #define LOG_INT(i)        printf("%s = %d
        ", #i, i)
        #define LOG_CHAR(c)       printf("%s = %c
        ", #c, c)
        #define LOG_FLOAT(f)      printf("%s = %f
        ", #f, f)
        #define LOG_POINTER(p)    printf("%s = %p
        ", #p, p)
        #define LOG_STRING(s)     printf("%s = %s
        ", #s, s)
        
        //封装遍历函数,while是为了保证使用的是代码块,防止变量的重复命名
        #define FOREACH(i, n)     while(1) { int i = 0, l = n; for(i=0; i < l; i++)
        #define BEGIN             {
        #define END               } break; } 
        
        int main()
        {
            int* pi = MALLOC(int, 5);
            char* str = "ABCD";
            
            LOG_STRING(str);
            
            LOG_POINTER(pi);
            
            FOREACH(k, 5)
            BEGIN
                pi[k] = k + 1;
            END
            
            //这里也可以使用FOREACH(k,5),不会发生变量名冲突
            FOREACH(n, 5)
            BEGIN
                int value = pi[n];
                LOG_INT(value);
            END
            
            FREE(pi);
            
            LOG_POINTER(pi);
            
            return 0;
        }
        
      • 编译运行

        str = ABCD
        pi = 0x8b4b008
        pi = (nil)
        value = 1
        value = 2
        value = 3
        value = 4
        value = 5
        pi = (nil)
        
  • 相关阅读:
    HDFS进阶
    sql 自连接 优化
    爬虫初探-笔趣阁小说下载
    Uos 系统访问局域网下的windows 系统文件
    统信Uos 操作系统--ThinkPad x280 机 安装后无法调节亮度
    Hadoop源码分析-hdfs(2)-NameNode类探索
    Hadoop源码分析-hdfs(1)-启动脚本分析
    设计模式学习笔记(4)-接口和抽象类
    设计模式学习笔记(3)-面向对象与面向过程
    设计模式学习笔记(2)-面向对象基本概念和四大特性
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13774048.html
Copyright © 2011-2022 走看看