当前位置: 首页 > news >正文

#define用法

C语言中,可以用 #define 定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。

预编译又叫预处理预编译不是编译,而是编译前的处理。这个操作是在正式编译之前由系统自动完成的。

用 #define 定义标识符的一般形式为:

#define  标识符  常量   //注意, 最后没有分号

#define 和 #include 一样,也是以“#”开头的。凡是以“#”开头的均为预处理指令,#define也不例外。

#define又称宏定义,标识符为所定义的宏名,简称宏。标识符的命名规则与前面讲的变量的命名规则是一样的。#define 的功能是将标识符定义为其后的常量。一经定义,程序中就可以直接用标识符来表示这个常量。是不是与定义变量类似?但是要区分开!变量名表示的是一个变量,但宏名表示的是一个常量。可以给变量赋值,但绝不能给常量赋值。

宏所表示的常量可以是数字、字符、字符串、表达式。其中最常用的是数字。

那么,程序中什么时候会使用宏定义呢?用宏定义有什么好处呢?我们直接写数字不行吗?为什么要用一个标识符表示数字呢?

宏定义最大的好处是“方便程序的修改”。使用宏定义可以用宏代替一个在程序中经常使用的常量注意,是“经常”使用的。这样,当需要改变这个常量的值时,就不需要对整个程序一个一个进行修改,只需修改宏定义中的常量即可。且当常量比较长时,使用宏就可以用较短的有意义的标识符来代替它,这样编程的时候就会更方便,不容易出错。因此,宏定义的优点就是方便和易于维护。

那么程序在预编译的时候是怎么处理宏定义的呢?或者说是怎么处理预处理指令的呢?

其实预编译所执行的操作就是简单的“文本”替换。对宏定义而言,预编译的时候会将程序中所有出现“标识符”的地方全部用这个“常量”替换,称为“宏替换”或“宏展开”。替换完了之后再进行正式的编译。所以说当单击“编译”的时候实际上是执行了两个操作,即先预编译,然后才正式编译#include<stdio.h>也是这样的,即在预处理的时候先单纯地用头文件stdio.h中所有的“文本”内容替换程序中#include<stdio.h>这一行,然后再进行正式编译。

需要注意的是,预处理指令不是语句,所以后面不能加分号。这是很多新手经常犯的错误。#include 后面也没有加分号。

宏定义 #define 一般都写在函数外面,与 #include 写在一起。当然,写在函数里面也没有语法错误,但通常不那么写。#define 的作用域为自 #define 那一行起到源程序结束如果要终止其作用域可以使用 #undef 命令,格式为:

#undef  标识符

undef 后面的标识符表示你所要终止的宏。比如前面在程序开头用 define 定义了一个宏 M,它原本的作用范围是一直到程序结束,但如果现在在程序中某个位置加了一句:

#undef M

那么这个宏的作用范围到此就结束了。#undef 用得不多,但大家要了解。

为了将标识符与变量名区别开来,习惯上标识符全部用大写字母表示。宏定义用得最多的地方是在数组中用于指定数组的长度。下面来写一个程序:

# include <stdio.h>
# define NUM 5
int main(void)
{
    int i, j = NUM;
    int a[NUM] = {0};
    printf("请输入%d个数:", j);
    for (i=0; i<NUM; ++i)
    {
        scanf("%d", &a[i] );
    }
    for (i=0; i<NUM; ++i)
    {
        printf("%d\x20", a[i]);
    }
    printf("\n");
    return 0;
}
输出结果是:

请输入5个数:5 4 3 2 1
5 4 3 2 1

NUM 是定义的宏,它表示的是其后的常量(而不是变量)。此外,程序中用双引号括起来的宏在预处理的时候是不会被宏替换的。因为在 C 语言中,用双引号括起来表示的是字符串。下面再写一个程序看一下:

# include <stdio.h>
# define PI 3.14159
int main(void)
{
    double r, s;
    printf("请输入圆的半径:");
    scanf("%lf", &r);  //scanf中, double只能用%lf
    s = PI * r * r;
    printf("s=PI*r^2 = %.6f\n", s);  //PI不会被宏替换
    return 0;
}

输出结果是:
请输入圆的半径:1
s=PI*r^2 = 3.141590

相关文章:

  • c语言预处理命令
  • C++头文件和std命名空间
  • C++输入输出(cin和cout)
  • C++运算符重载的概念和语法
  • GetLastError,ErrLookUp,$err,hr,$eax
  • 字符集和字符编码(Charset Encoding)
  • 进程
  • Windows中的对象
  • Windows对象、句柄与MFC对象
  • C++结构体
  • C++ 指针运算符( 和 *)
  • C++中 引用与取地址的区别
  • C/C++语言中函数参数传递的三种方式(x,*x,x)
  • VC 和 VS 区别
  • 什么是Windows API
  • 【5+】跨webview多页面 触发事件(二)
  • django开发-定时任务的使用
  • Github访问慢解决办法
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • Python打包系统简单入门
  • SOFAMosn配置模型
  • Spring Boot MyBatis配置多种数据库
  • TCP拥塞控制
  • 简单实现一个textarea自适应高度
  • 坑!为什么View.startAnimation不起作用?
  • 世界上最简单的无等待算法(getAndIncrement)
  • 找一份好的前端工作,起点很重要
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • Nginx惊现漏洞 百万网站面临“拖库”风险
  • ​七周四次课(5月9日)iptables filter表案例、iptables nat表应用
  • # 飞书APP集成平台-数字化落地
  • #laravel 通过手动安装依赖PHPExcel#
  • #微信小程序:微信小程序常见的配置传旨
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • $ is not function   和JQUERY 命名 冲突的解说 Jquer问题 (
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (poj1.3.2)1791(构造法模拟)
  • (定时器/计数器)中断系统(详解与使用)
  • (四)JPA - JQPL 实现增删改查
  • (万字长文)Spring的核心知识尽揽其中
  • (一)基于IDEA的JAVA基础10
  • (自适应手机端)响应式新闻博客知识类pbootcms网站模板 自媒体运营博客网站源码下载
  • .Net 4.0并行库实用性演练
  • .NET 4.0中使用内存映射文件实现进程通讯
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET 指南:抽象化实现的基类
  • .net下简单快捷的数值高低位切换
  • /etc/shadow字段详解
  • /etc/sudoer文件配置简析
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • [BJDCTF2020]The mystery of ip1
  • [C++]类和对象【上篇】
  • [CSAWQual 2019]Web_Unagi ---不会编程的崽