C++宏定义

一、宏定义:

#define命令进行宏定义,他将一个标示符定义为一个字符串,标示符称为宏名,字符串称为替代文本;

#define命令有两种格式:简单的宏定义和带有参数的宏定义
1、简单的宏定义:

#define <宏名> <字符串>如:#define PI 3.14

2、带有参数的宏定义

#define <宏名>(<参数表>) <宏体> 如:#define A(x) x

在程序被编译之前,先将宏名用被定义的字符串替换,称为宏替换,替换后才进行编译。

二、宏替换的时机:

源程序处理过程:预处理---编译----汇编---链接,其中宏替换就是在预处理的过程中进行的

1)文件包含:可以把源程序中的#include扩展为文件正文,即把头文件找到并展开到#include所在处;

2)条件编译:预处理器根据#if或#ifdef等编译命令及其后的条件将源程序中的某部分包含进来或排除在外,通常把排除在外的语句换成空行;

3)宏展开:预处理器将源程序中出现的对宏的引用展开成相应的宏定义

经过预处理的源程序和原来的源程序有所不同,但是这个阶段所进行的工作只是纯粹的展开和替换,没有任何计算工作

三、#define常见问题

1)简单的宏定义中出现的问题:

代码如下:

  1. 例1:
  2.  #define N 2+2
  3. void main()
  4. {
  5.    int a=N*N;
  6.    printf(%d”,a);
  7. }
  8. 输出为8,不为16
  9. 分析:其中N代表的是2+2,一般同学在读到这个程序时,会反应成N=2+2=4,然后a的输出为16,这是错误的,答案应该是8,原因是宏替换是发生在预处理阶段,这个阶段只进行简单的替换,而不会有计算的功能,所以N代表的是字符串2+2而不是4,那么a=2+2*2+2,按照运算符的优先级,应该=8,而不是4*4=16.
  10. 如果想达到16这个结果,可以改正一下源程序#define N (2+2),这样的话,结果就会是16.

  11. 2)带参数的宏定义出现的问题
  12. 以求平方的函数为例:
  13. 一般同学会这样写:
    1. #define area(x) x*x
    2. /*这在使用中是很容易出现问题的,看如下的程序*/

    3. void main()
    4. {
    5.     int y = area(2+2);
    6.     printf(%d”,y);
    7. }
    8. 输出结果为8,不为16,原因如上面所说,把参数x用2+2替换,那么y=2+2*2+2=8
    9. 所以好的编程喜欢是这样的:#define area(x) (x)*(x)
    10. 如果y=area(2+2)/area(2+2),一般人一看分子分母相同,觉得会是1,那就错了,我们分解一下:
    y=(2+2)*(2+2)/(2+2)*(2+2)=4*4/4*4=16,
    所以更好的编程习惯是这样的:#define area(x) ((x)*(x)),这个非常有必要
    所以如果是自己编程使用宏替换,则在使用简单宏定义时,当字符串中不只一个符号时,加上括号表现出优先级,如果是带参数的宏定义,则要给宏体中的每个参数加上括号,并在整个宏体上再加一个括号
    四、#define中的三个特殊符号:##、#、#@
    1)##表示连接,如
    #define Conn(x,y) x##y
    1. int n = Conn(123,456); /* 结果就是n=123456;*/
    2. char* str = Conn("asdf", "adf"); /*结果就是 str = "asdfadf";*/
    3. 2)#@表示给结果加上一个单引号,返回一个const char类型,如:
    4. #define ToChar(x) #@x
    5. char a = ToChar(1);结果就是a='1'
    6. 如果参数超过四个字符,就会报错
    7. 3)#表示给结果加上一个双引号,返回一个char* 类型,如:
    8. #define ToString(x) #x
    9. char* str = ToString(123132);就成了str="123132"
    10. 五、常用的宏定义
    11. 1)防止头文件被重复包含
    12. #ifndef HELLO_H
    13. #define HELLO_H
    14. ....(此处包含头文件)
    15. #endif
    16. 2)得到指定地址上的一个字节或一个字
      1. #define MEM_B( x ) ( *( (byte *) (x) ) ) 
      2. #define MEM_W( x ) ( *( (word *) (x) ) )
      1. #include <iostream>
      2. #include <windows.h>

      3. #define MEM_B(x) (*((byte*)(x)))
      4. #define MEM_W(x) (*((WORD*)(x)))

      5. int main()
      6. {
      7.     int bTest = 0x123456;

      8.     byte m = MEM_B((&bTest));/*m=0x56*/
      9.     int n = MEM_W((&bTest));/*n=0x3456*/

      10.     return 0;
      11. }
      3)ANSI中定义的宏:
    17. __LINE__    对应%d,注意前后都是双下划线,表示__LINE__所在的行号
    18. __FILE__    对应%s,源文件的文件路径
    19. __DATE__    对应%s,日期
    20. __TIME__    对应%s,时间
    21. 如:
    22. 1// test_base1.cpp : Defines the entry point for the console application.
      2#include "stdafx.h"
      3#include "stdio.h"
      4#line 50
      5int main(int argc, char* argv[])
      6{
      7 int n;
      8 int line = __LINE__; //注意前后都是双下划线
      9 char file[] = __FILE__;
      10 char date[] = __DATE__;
      11 char time[] = __TIME__;
      12 printf("line=%d\n,file=%s\n,date=%s\n,time=%s\n",line,file,date,time);
      13 return 0;
      14}
    23. 如果没有#line 50,那么输出的结果为
    24. 如果有#line 50,输出结果为:

    25. #line 50表示,#line 50的下一行为第50行







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值