预处理

预处理

预定义符号

__FILE__        //当前编译的文件名
__DATE__     //文件被编译的日期
__TIME__      //文件被编译的时间
__FUNCTION__    //当前所在函数的函数名
//以上格式占用符都用%s,如printf("%s",__DATE__);
__LINE__       //文件当前的行号,格式占用符用%d,如:printf("%d",LINE);
/*注意以上这些宏定义的前后分别有两个'_',而不是一个下划线*/
_CRT_SECURE_NO_WAENINGS//关闭安全检查

宏定义

宏定义:又称为宏替换,自定义一个宏(要符合标识符的命名规则),用于替换任意数据/标识符/表达式。
作用:对源程序编译之前做一些处理,生成扩展C源程序

l种类
宏定义 #define
文件包含 #include
条件编译 #if--#else--#endif等

l格式:
“#”开头
占单独书写行
语句尾不加分号

1.不带参数宏定义

•一般形式: #define 宏名 [宏体]
•功能:用指定标识符(宏名)代替字符序列(宏体)
定义位置:任意(一般在函数外面)
作用域:从定义命令到文件结束

undef可终止宏名作用域

 格式:   #undef     宏名

宏定义可以嵌套,不能递归
例 #define MAX MAX+10 (错)

#include<stdio.h>
#define    YES       1//y原作用域
int main()
{
    //......
}
#undef   YES
#define    YES    0//y新作用域
 max()
 {
    //......
 }

宏展开:预编译时,用宏体替换宏名--不作语法检查
(引号中的内容与宏名相同也不置换)

//例:
#define   PI    3.14159
    printf(“2*PI=%fn”,PI*2);
//宏展开:
    printf(“2*PI=%fn”,3.14159*2);

2.带参数宏定义

•一般形式: #define 宏名(参数表) 宏体
宏名与参数表之间不能加空格

//例
#define    S(a,b)    a*b
      ......
       area=S(3,2);
宏展开:area=3*2;
//例
#define   POWER(x)      x*x
      x=4;   y=6;
      z=POWER(x+y);
宏展开:z=x+y*x+y;
//因此,使用带参数的宏定义的时候注意宏体的形式,注意括号的使用
一般写成:  #define    POWER(x)    ((x)*(x))
宏展开:  z=((x+y)*(x+y));
//例  用宏定义和函数实现同样的功能

//宏定义表达形式
#define  MAX(x,y)   (x)>(y)?(x):(y)
......
main()
{   int  a,b,c,d,t;
    ......
     t=MAX(a+b,c+d);
    ......
}
宏展开:t=(a+b)>(c+d)?(a+b):(c+d);

//函数形式
int   max(int x,int y)
{  return(x>y?x:y);
}
main()
{    int a,b,c,d,t;
     ......
     t=max(a+b,c+d); 
     ......
}
带参宏 函数
处理时间 编译时 程序运行时
参数类型 无类型问题 定义实参,形参类型
处理过程 不分配内存简单的字符置换 分配内存,先求实参值,再代入形参
程序长度 变长 不变
运行速度 不占用运行时间 调用和返回占用时间

文件包含

使用用库函数就需要包含头文件,也就是文件包含,可以编写自定义头文件,包含自己编写的头文件。

文件包含的基本格式

include<文件名>或#include"文件名"

#include<stdio.h>//包含系统的头文件用<>,只会在系统头文件找
#include"name.h"//包含自定义头文件用""(在自定义头文件中找不到就会在系统头文件中找)
//文件包含允许嵌套,即在一个被包含文件中可以包含其他文件。

头文件的定义和使用

//头文件的定义需要两个文件来创建(头文件声明,源文件定义)
1.在解决方案资源管理器中右键头文件创建一个新的头文件命名为···.h,例:text.h
    在这个头文件中只负责声明函数,不负责定义
2.在源文件中创建同名文件为···.c,例:text.c
    这个源文件负责定义函数
3.在主要的文件中调用头文件。例:#include"text.h"
#注意事项
如果头文件A包含头文件C,同时头文件B也包含头文件C,而写的程序中包含了头文件A,头文件B,然后在编译的时候就会出现头文件C重复包含的错误.
这种错误叫做头文件的重复包含。
1.使用#pragma once可以解决这个问题(vs独有,有平台限制)(在自己编写的头文件中使用,而不是源文件)
2.头文件加#ifndef 宏名  #define 宏名  #endif
    两者区别:
   (1)#ifndef 和#pragma once都发生在预处理阶段,#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”。
   (2)#ifndef是C/C++语言特性,而#pragma once是编译器提供的指令,同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。
   (3)#pragma依赖于编译器,所以一些老的编译器不提供(比如说vc6之前),而#ifndef可移植性非常好。
文件text.h:
目的:为了避免同一个文件被include多次
#pragma once  //防止头文件的重复包含产生冲突
#ifndef __TEXT_H__//防止一个源文件两次包含同一个头文件
#define __TEXT_H__

    /*文件名叫什么就宏定义为大写的格式:*/
    /*例:文件name.h->宏定义#ifndef __NAME_H__   #define __NAME_H__ */ 
    void fun();//函数的声明,头文件只能在这个文件中声明
......其他函数
#endif//文件结束

预处理

预处理

预处理

!!后面两个文件的后缀是.c而不是.cpp,不然会报错

条件编译

if #else #ifdef #ifndef

使用方法:
#if+条件(真/假)
       代码: 。。。。。。(如果为真,则运行这些代码)
#else
       代码: 。。。。。。(如果为假,则运行这些代码)
#endif(结束)注意#endif不可缺少**

#ifdef  A(如果定义了A)
#ifndef A(如果没有定义A)
上面两个语句可以代替#if

原文链接: https://www.cnblogs.com/ningcode/p/17058808.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    预处理

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/312799

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 下午12:32
下一篇 2023年2月16日 下午12:32

相关推荐