C语言学习笔记(浙大翁恺版)第十二周 文件(2)

目录

12.2.1 宏定义

编译与预处理指令

 #define

宏 

没有值的宏

一些预定义的宏

12.2.2 带参数的宏

像函数的宏

错误定义的宏

带参数的宏的原则

带多个参数的宏

分号?

带参数宏小知识


12.2.1 宏定义

编译与预处理指令

  • #开头的都属于编译预处理指令(它们不是C语言的成分,但C语言离不开它们)
  • #define用来定义一个宏
    • 编译预处理的流程:.c->.i(编译预处理完成)->.s(编译器编译,汇编代码文件)->.o(目标代码文件)->a.out(完成链接,生成可执行文件)
#include<stdio.h>
//当你需要定义一个常量...
const double PI = 3.14159;//C99
#define PI 3.14159//老版本C,
//定义一个符号————宏,名为PI,值为3.14159
编译预处理阶段会将所有PI替换为3.14159,简单的文本替换

int main()
{
    printf("%f\n",2*PI*3.0);
    
    return 0;
}

 #define

  • #define <名字> <值> (不需要等号。也没有分号,因为不属于C语句)
  • 名字必须是一个单词,值可以是任意的类型
  • 一个编译预处理指令,在编译之前完成文本替换

宏 

  •  如果一个宏里有别的宏名字,会被替换
  • 如果一个宏的值超过一行,最后一行之前的行末要加反斜杠
  • 宏的值后面出现的注释不会被当作宏的值
#include<stdio.h>

#define PI 3.14159
#define PI2 2*PI //就是Π乘以2

#define PRINT printf("%f\n",2*PI*3.0);\//此时就是分行的写法,第一句得写分号
              printf("%f\n",2*PI*3.0)

int main()
{
    printf("%f\n",2*PI*3.0);
    printf("%f\n",PI2*3.0);
    PRINT;
    return 0;
}

 三次结果完全相同。

没有值的宏

  • #define _DEBUG,告诉编译器有这个宏,但不需要有值
  • 这类宏是用于条件编译的,后面有其他的编译预处理指令来检查这个宏是否被定义过

一些预定义的宏

  • _LINE_ //用来获取行号
  • _FILE_ //用来获取文件名
  • _DATE_ //用来获取编译时的日期
  • _TIME_ //用来获取编译时的时间
  • _STDC_

试试这个程序吧!

#include<stdio.h>

int main()
{
    printf("%s:%d\n",_FILE_,_LINE_);
    printf("%s:%d\n",_DATE_,_TIME_);

    return 0;
}

12.2.2 带参数的宏

除了简单的替换文本的宏,还可以定义一些带参数的

像函数的宏

#include<stdio.h>
#define cube(x) ((x)*(x)*(x))//名字和值都可以带参数,原理一样是替换

int main()
{
    printf("%d\n",cube(5));//是不是很像调用函数?
    return 0;
}
另一个程序,同样的预编译语句
int main()
{
    int i;
    scanf("%d",&i);
    printf("%d\n",cube(i+2));//此处会被替换为
                    //((i+2)*(i+2)*(i+2))
    return 0;
}

看起来相当完美,你甚至不需要写函数了!然而新手是会犯错的

错误定义的宏

#define RadToDeg1(x) (x*57.29578)
#define RadToDeg2(x) (x)*57.29578

int main()
{
    printf("%f\n",RadToDeg1(5+2));//x=7 大概400多

    printf("%f\n",180/RadToDeg2(1));//180除以57,等于3左右

    return 0;
}

 

怎么会相差如此之多?我们需要看看它被替换成了什么

 我们的本意是让180先除以57.多,然后再乘1,但是运算反了,这是为什么?

带参数的宏的原则

#define RadToDeg1(x) (x*57.29578)
#define RadToDeg2(x) (x)*57.29578

 仔细观察下,第二句之所以出错,是因为57点多暴露在外面,因此原则上,带参数的宏必须套上括号

  • 一切都要有括号(整个宏需要有括号,每个参数需要有括号)
  • 所以上面的两个宏都不规范,应该写为:
#define RadToDeg1(x) ((x)*57.29578)

带多个参数的宏

  • 一个宏可以带多个参数,也可以组合(嵌套)使用其他宏
#define MIN(a,b) ((a)>(b)?(b):(a))

分号?

图中的三个分号,写上之后各个语句都被分开,是不能使用的

带参数宏小知识

  • 在大型程序中非常常见,可以非常复杂(代替函数,牺牲空间换取效率,有#和##的帮助)
  • 中西程序员对其应用程度不同,属于小的文化差异。西方人会将其做的相当复杂
  • 传递参数时没有类型检查,inline函数机制可以取代宏定义方式,可以帮忙解决这种问题

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值