[CC++] 预处理

[CC++] 预处理,第1张

1程序的翻译与执行环境

执行是涉及硬件的,不是这系列的重点

  • 编译部分是将源文件xxx.c通过编译器编译成xxx.obj
  • 链接部分是将xxx.obj+链接库放到链接器中链接成可执行程序


  • 在汇编阶段,把各个文件的全局符号生成对应的符号表xxx.o;在链接阶段,把各个符号表进行汇总,如果发现有无法解析的函数地址,则出现错误
2预处理! 2.1预定符号
  • 这些是内置好的符号
  • __FILE__;当前编译源文件的路径
  • __LINE__;该代码当前所在的行号
  • __DATE__;当前日期
  • __TIME__;当前时间
  • __FUNCTION__;当前的所在的函数名
  • __LINE__;
  • 以上通常是为了写log用的
2.2#define
  • #define M 100
  • #define reg register
  • #define do_forever for(…;…;…)
  • #define CASE break;case
  • 就是可以自己定义一段东西,在预处理时直接替换
  • 加;就是会在预处理时加上分号,所以要斟酌使用
2.3#define 定义宏
  • #define SQUARE(X) X*X

宏的一个缺陷

由于宏#define是一个预编译的 *** 作,相关的运算并不是在预编译中进行的,所以会出现如下情况

#define SQUARE(X) X*X
//#define SQUARE(X) ((X)*(X))//如果想要3*3的效果,得这么改,括号不能省
#include
using namespace std;

int main()
{
    cout<
2.4#(非define哪个)和##
  • 将#x的内容替换成对应的字符串(而非变量值)

  • 只能在宏中使用

#define PRINT(X,F) printf("the value of  "#X" is "F,X);

int main()
{
    int a  =10;
    PRINT(a,"%d");
    int b = 20;
    PRINT(b,"%d");

    float f = 2.5f;
    PRINT(f,"%f");
    return 0;
}

##的使用

  • 把两个字符串合在一起
2.5带副作用的宏参数

主要出现在a++,++a这种,因为他是完全替换。这是一种危险的编程行为。

2.6宏和函数的对比

宏的优势

  • 宏:直接在预处理阶段完全替换,所需要的的汇编代码是更少的。他跟inline很像,但是inline实在编译期间展开的,且本质时函数。
  • 函数:需要做相当多的准备工作,编译,才能进行核心的汇编代码。
  • 如果调用+返回的过程比实际执行小型计算时更长,应该用宏。
  • 此外,函数需要明确的类型,而宏允许其他类型,此时宏更为灵活,如:
      #define MAX(X,Y) ((X)>(Y)?(X):(Y))
    
      int Max(int x,int y)
      {
          return x>y?x:y;
      }
    

宏的劣势

  • 由于是完全替换,即实际上会插入到程序中。因此一般建议宏是一个小巧的功能。而函数不是,函数是专门开辟了一片内存空间的,使用时就去那片空间找。
  • 宏没办法debug!因为调试是在代码编译,链接后形成.exe时才能debug,而宏在预处理阶段已经全部替换了。
  • 宏由于没有明确类型定义,缺乏严谨性
  • 括号少括了, *** 作符的优先级,会导致未知错误
  • 宏不允许递归
2.7#undef

取消一个定义

2.8条件编译,跟条件判断类似,预处理时跟注释类似
  1. #define PRINT
     int main()
     {
         //如果PRINT定义了就编译
     #ifdef PRINT
         printf("1");
     #endif
         return 0;
     }
    
  2. #if
    
    #elif
    
    #else
    
    #endif
    
  3.  //如果HEHE不定义,下面参与编译
     #ifndef HEHE
     #endif
    
  4. 允许嵌套
     #if defined(OS_UNIX)
         #ifdef OPTION1
             unix_version_option1();
         #endif
     #endif
    
2.9文件包含
  • 自己定义的头文件用#include “add.h”,来引入。称为本地文件的包含。他会在本地位置查找,如果找不到则去库函数的头文件目录下找

  • #include ,为库文件的包含。<>直接去库函数里面找。

  • 防止头文件被重复包含用
    :
    第一种:#pragma once

    第二种:

    #ifndef __TEST_H__

    #define __TEST_H__

    #endif

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/713523.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-24
下一篇 2022-04-24

发表评论

登录后才能评论

评论列表(0条)