当前位置:首页 » 编程软件 » 预编译命令无参数定义

预编译命令无参数定义

发布时间: 2022-09-05 05:15:29

c语言编译预处理命令”,是什么意思

您好,
宏定义
c程序提供的预处理功能之一。包括带参数的宏定义和不带参数的宏定义。具体是指用一个指定的标志符来进行简单的字符串替换或者进行阐述替换。形式为:
#define
标志符(参数表)
字符串
宏名
在上定义中的标志符被称为“宏名”。
宏展开
在c程序编译时将宏名替换成字符串的过程称为“宏展开”。
define
是对宏的定义:如定义了一个宏m,代表100.也就在下面的程序中只要是遇到变量m,它的值就是100

② typedef和define具体的详细区别

区别如下:

(1)原理不同

#define是C语言中定义的语法,是预处理指令,在预处理时进行简单而机械的字符串替换,不作正确性检查,只有在编译已被展开的源程序时才会发现可能的错误并报错。

typedef是关键字,在编译时处理,有类型检查功能。它在自己的作用域内给一个已经存在的类型一个别名,但不能在一个函数定义里面使用typedef。用typedef定义数组、指针、结构等类型会带来很大的方便,不仅使程序书写简单,也使意义明确,增强可读性。

(2)功能不同

typedef用来定义类型的别名,起到类型易于记忆的功能。另一个功能是定义机器无关的类型。如定义一个REAL的浮点类型,在目标机器上它可以获得最高的精度:typedef long double REAL, 在不支持long double的机器上,看起来是这样的,typedef double REAL,在不支持double的机器上,是这样的,typedef float REAL

#define不只是可以为类型取别名,还可以定义常量、变量、编译开关等。

(3)作用域不同

#define没有作用域的限制,只要是之前预定义过的宏,在以后的程序中都可以使用,而typedef有自己的作用域。

(4)对指针的操作不同

#define INTPTR1 int*

typedef int* INTPTR2;

INTPTR1 p1, p2;

INTPTR2 p3, p4;

含义分别为,

声明一个指针变量p1和一个整型变量p2

声明两个指针变量p3、p4

#define INTPTR1 int*

typedef int* INTPTR2;

int a = 1;

int b = 2;

int c = 3;

const INTPTR1 p1 = &a;

const INTPTR2 p2 = &b;

INTPTR2 const p3 = &c;

上述代码中,

const INTPTR1 p1是一个常量指针,即不可以通过p1去修改p1指向的内容,但是p1可以指向其他内容。

const INTPTR2 p2是一个指针常量,不可使p2再指向其他内容。因为INTPTR2表示一个指针类型,因此用const限定,表示封锁了这个指针类型。

INTPTR2 const p3是一个指针常量

(2)预编译命令无参数定义扩展阅读:

define的作用:

被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。

宏定义的作用范围仅限于当前文件,即file1.c中定义 #define PI 3.14,在file2.c中该宏定义不起作用;通过将#define PI 3.14定义在common.h中,file1.c和file2.c分别#include "common.h"的方式,该宏定义在file1.c和file2.c中都起作用。

在C或C++语言中,“宏”分为有参数和无参数两种。

参考资料:

typedef-网络

③ C语言提供的预编译处理命令主要有哪三种

1.宏定义:用一个指定的标识符(即名字)来代表一个字符串,如:用PI代表3.1415926,#define PI 3.1415926
2.文件包含:指一个源文件可以将另外一个源文件的全部内容包含进来,#include<文件名>
3.条件编译:对一部分内容指定编译的条件,即满足一定的条件才编译,主要有:
(1)#ifdef标识符
程序段1
#eles
程序段2
#endif
(2)#ifndef标识符
程序段1
#eles
程序段2
#endif
(3))#if标识符
程序段1
#eles
程序段2
#endif

④ C语言预编译命令

#include <assert.h> //设定插入点
#include <ctype.h> //字符处理
#include <errno.h> //定义错误码
#include <float.h> //浮点数处理
#include <fstream.h> //文件输入/输出
#include <iomanip.h> //参数化输入/输出
#include <iostream.h> //数据流输入/输出
#include <limits.h> //定义各种数据类型最值常量
#include <locale.h> //定义本地化函数
#include <math.h> //定义数学函数
#include <stdio.h> //定义输入/输出函数
#include <stdlib.h> //定义杂项函数及内存分配函数
#include <string.h> //字符串处理
#include <strstrea.h> //基于数组的输入/输出
#include <time.h> //定义关于时间的函数
#include <wchar.h> //宽字符处理及输入/输出
#include <wctype.h> //宽字符分类

//////////////////////////////////////////////////////////////////////////

标准 C++ (同上的不再注释)

#include <algorithm> //STL 通用算法
#include <bitset> //STL 位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex> //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque> //STL 双端队列容器
#include <exception> //异常处理类
#include <fstream>
#include <functional> //STL 定义运算函数(代替运算符)
#include <limits>
#include <list> //STL 线性列表容器
#include <map> //STL 映射容器
#include <iomanip>
#include <ios> //基本输入/输出支持
#include <iosfwd> //输入/输出系统使用的前置声明
#include <iostream>
#include <istream> //基本输入流
#include <ostream> //基本输出流
#include <queue> //STL 队列容器
#include <set> //STL 集合容器
#include <sstream> //基于字符串的流
#include <stack> //STL 堆栈容器
#include <stdexcept> //标准异常类
#include <streambuf> //底层输入/输出支持
#include <string> //字符串类
#include <utility> //STL 通用模板类
#include <vector> //STL 动态数组容器
#include <cwchar>
#include <cwctype>

using namespace std;

//////////////////////////////////////////////////////////////////////////

C99 增加

#include <complex.h> //复数处理
#include <fenv.h> //浮点环境
#include <inttypes.h> //整数格式转换
#include <stdbool.h> //布尔环境
#include <stdint.h> //整型环境
#include <tgmath.h> //通用类型数学宏

⑤ 预处理命令的宏定义

1.不带参数的宏定义:
宏定义又称为宏代换、宏替换,简称“宏”。
格式:
#define标识符文本
其中的标识符就是所谓的符号常量,也称为“宏名”。
预处理(预编译)工作也叫做宏展开:将宏名替换为文本(这个文本可以是字符串、可以是代码等)。
掌握宏概念的关键是“换”。一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。
即在对相关命令或语句的含义和功能作具体分析之前就要换:
例:
#define PI 3.1415926
把程序中全部的标识符PI换成3.1415926
说明:
(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如:数组大小常用宏定义
(3)可以用#undef命令终止宏定义的作用域
(4)宏定义可以嵌套
2.带参数的宏:
除了一般的字符串替换,还要做参数代换
格式:
#define 宏名(参数表)文本
例如:#define S(a,b) a*b
area=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2;
类似于函数调用,有一个哑实结合的过程:
(1)实参如果是表达式容易出问题
#define S(r) r*r
area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;
正确的宏定义是#define S(r) ((r)*(r))
(2)宏名和参数的括号间不能有空格
(3)宏替换只作替换,不做计算,不做表达式求解
(4)函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)宏展开使源程序变长,函数调用不会
(7)宏展开不占运行时间,只占编译时间,函数调用占运行时间(分配内存、保留现场、值传递、返回值)

⑥ c程序在执行过程中对预处理命令进行处理这一说法为什么是错误的

C语言在编译前由预处理器对预处理命令进行处理,编译时进行语法分析。执行过程就是运行程序。

程序设计语言的预处理的概念:在编译之前进行的处理。

C语言的预处理主要有三个方面的内容:

1、宏定义;

2、文件包含;

3、条件编译。 预处理命令以符号“#”开头。

C程序的源代码中可包括各种编译指令,这些指令称为预处理命令。虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境。本节将介绍如何应用预处理程序和注释简化程序开发过程,并提高程序的可读性。

(6)预编译命令无参数定义扩展阅读

C语言无参数宏定义

在C语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。

宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。在C语言中,“宏”分为有参数和无参数两种。本节讨论无参数宏。

无参宏的宏名后不带参数。其定义的一般形式为:#define 标识符 字符串

其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。

在前面介绍过的符号常量的定义就是一种无参宏定义。此外,常对程序中反复使用的表达式进行宏定义。例如:#define M (y*y+3*y)

⑦ C中预定义标识符define include undef ifdef ifndef endif line 的用法以及意义最好带例子

由预处理程序自动完成的。在C语言中,“宏”分为有参数和无参数两种。 下面分别讨论这两种“宏”的定义和调用。

无参宏定义
无参宏的宏名后不带参数。其定义的一般形式为: #define 标识符 字符串 其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。 “标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。在前面介绍过的符号常量的定义就是一种无参宏定义。 此外,常对程序中反复使用的表达式进行宏定义。例如: # define M (y*y+3*y) 定义M表达式(y*y+3*y)。在编写源程序时,所有的(y*y+3*y)都可由M代替,而对源程序作编译时,将先由预处理程序进行宏代换,即用(y*y+3*y)表达式去置换所有的宏名M,然后再进行编译。
#define M (y*y+3*y)
main(){
int s,y;
printf("input a number: ");
scanf("%d",&y);
s=3*M+4*M+5*M;
printf("s=%d\n",s);
}
上例程序中首先进行宏定义,定义M表达式(y*y+3*y),在s= 3*M+4*M+5* M中作了宏调用。在预处理时经宏展开后该语句变为:s=3*(y*y+3*y)+4(y*y+3*y)+5(y*y+3*y);但要注意的是,在宏定义中表达式(y*y+3*y)两边的括号不能少。否则会发生错误。
当作以下定义后: #difine M y*y+3*y在宏展开时将得到下述语句: s=3*y*y+3*y+4*y*y+3*y+5*y*y+3*y;这相当于; 3y�2+3y+4y�2+3y+5y�2+3y;显然与原题意要求不符。计算结果当然是错误的。 因此在作宏定义时必须十分注意。应保证在宏代换之后不发生错误。对于宏定义还要说明以下几点:

1. 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。

2. 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。

3. 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结 束。如要终止其作用域可使用# undef命令,例如: # define PI 3.14159
main()
{
……
}
# undef PIPI的作用域
f1()
....表示PI只在main函数中有效,在f1中无效。
4. 宏名在源程序中若用引号括起来,则预处理程序不对其作宏代换。
#define OK 100
main()
{
printf("OK");
printf("\n");
}
上例中定义宏名OK表示100,但在printf语句中OK被引号括起来,因此不作宏代换。程序的运行结果为:OK这表示把“OK”当字符串处理。

5. 宏定义允许嵌套,在宏定义的字符串中可以使用已经定义的宏名。在宏展开时由预处理程序层层代换。例如: #define PI 3.1415926
#define S PI*y*y /* PI是已定义的宏名*/对语句: printf("%f",s);在宏代换后变为: printf("%f",3.1415926*y*y);

6. 习惯上宏名用大写字母表示,以便于与变量区别。但也允许用小写字母。

7. 可用宏定义表示数据类型,使书写方便。例如: #define STU struct stu在程序中可用STU作变量说明: STU body[5],*p;#define INTEGER int 在程序中即可用INTEGER作整型变量说明: INTEGER a,b; 应注意用宏定义表示数据类型和用typedef定义数据说明符的区别。宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简单的代换, 而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。请看下面的例子: #define PIN1 int* typedef (int*) PIN2;从形式上看这两者相似, 但在实际使用中却不相同。下面用PIN1,PIN2说明变量时就可以看出它们的区别: PIN1 a,b;在宏代换后变成 int *a,b;表示a是指向整型的指针变量,而b是整型变量。然而:PIN2 a,b;表示a,b都是指向整型的指针变量。因为PIN2是一个类型说明符。由这个例子可见,宏定义虽然也可表示数据类型, 但毕竟是作字符
代换。在使用时要分外小心,以避出错。

8. 对“输出格式”作宏定义,可以减少书写麻烦。例9.3 中就采用了这种方法。
#define P printf
#define D "%d\n"
#define F "%f\n"
main(){
int a=5, c=8, e=11;
float b=3.8, d=9.7, f=21.08;
P(D F,a,b);
P(D F,c,d);
P(D F,e,f);
}

带参宏定义

C语言允许宏带有参数。在宏定义中的参数称为形式参数, 在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开, 而且要用实参去代换形参。

带参宏定义的一般形式为: #define 宏名(形参表) 字符串 在字符串中含有各个形参。带参宏调用的一般形式为: 宏名(实参表);
例如:
#define M(y) y*y+3*y /*宏定义*/
:
k=M(5); /*宏调用*/
: 在宏调用时,用实参5去代替形参y, 经预处理宏展开后的语句
为: k=5*5+3*5
#define MAX(a,b) (a>b)?a:b
main(){
int x,y,max;
printf("input two numbers: ");
scanf("%d%d",&x,&y);
max=MAX(x,y);
printf("max=%d\n",max);
}
上例程序的第一行进行带参宏定义,用宏名MAX表示条件表达式(a>b)?a:b,形参a,b均出现在条件表达式中。程序第七行max=MAX(x,
y)为宏调用,实参x,y,将代换形参a,b。宏展开后该语句为: max=(x>y)?x:y;用于计算x,y中的大数。对于带参的宏定义有以下问题需要说明:

1. 带参宏定义中,宏名和形参表之间不能有空格出现。
例如把: #define MAX(a,b) (a>b)?a:b写为: #define MAX (a,b) (a>b)?a:b 将被认为是无参宏定义,宏名MAX代表字符串 (a,b)(a>b)?a:b。
宏展开时,宏调用语句: max=MAX(x,y);将变为: max=(a,b)(a>b)?a:b(x,y);这显然是错误的。

2. 在带参宏定义中,形式参数不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值。要用它们去代换形参,因此必须作类型说明。这是与函数中的情况不同的。在函数中,形参和实参是两个不同的量,各有自己的作用域,调用时要把实参值赋予形参,进行“值传递”。而在带参宏中,只是符号代换,不存在值传递的问题。

3. 在宏定义中的形参是标识符,而宏调用中的实参可以是表达式。
#define SQ(y) (y)*(y)
main(){
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=SQ(a+1);
printf("sq=%d\n",sq);
}
上例中第一行为宏定义,形参为y。程序第七行宏调用中实参为a+1,是一个表达式,在宏展开时,用a+1代换y,再用(y)*(y) 代换SQ,得到如下语句: sq=(a+1)*(a+1); 这与函数的调用是不同的, 函数调用时要把实参表达式的值求出来再赋予形参。 而宏代换中对实参表达式不作计算直接地照原样代换。

4. 在宏定义中,字符串内的形参通常要用括号括起来以避免出错。 在上例中的宏定义中(y)*(y)表达式的y都用括号括起来,因此结果是正确的。如果去掉括号,把程序改为以下形式:
#define SQ(y) y*y
main(){
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=SQ(a+1);
printf("sq=%d\n",sq);
}
运行结果为:input a number:3
sq=7 同样输入3,但结果却是不一样的。问题在哪里呢? 这是由于代换只作符号代换而不作其它处理而造成的。 宏代换后将得到以下语句: sq=a+1*a+1; 由于a为3故sq的值为7。这显然与题意相违,因此参数两边的括号是不能少的。即使在参数两边加括号还是不够的,请看下面程序:
#define SQ(y) (y)*(y)
main(){
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=160/SQ(a+1);
printf("sq=%d\n",sq);
}
本程序与前例相比,只把宏调用语句改为: sq=160/SQ(a+1); 运行本程序如输入值仍为3时,希望结果为10。但实际运行的结果如下:input a number:3 sq=160为什么会得这样的结果呢?分析宏调用语句,在宏代换之后变为: sq=160/(a+1)*(a+1);a为3时,由于“/”和“*”运算符优先级和结合性相同, 则先作160/(3+1)得40,再作40*(3+1)最后得160。为了得到正确答案应在宏定义中的整个字符串外加括号, 程序修改如下
#define SQ(y) ((y)*(y))
main(){
int a,sq;
printf("input a number: ");
scanf("%d",&a);
sq=160/SQ(a+1);
printf("sq=%d\n",sq);
}
以上讨论说明,对于宏定义不仅应在参数两侧加括号, 也应在整个字符串外加括号。

5. 带参的宏和带参函数很相似,但有本质上的不同,除上面已谈到的各点外,把同一表达式用函数处理与用宏处理两者的结果有可能是不同的。main(){
int i=1;
while(i<=5)
printf("%d\n",SQ(i++));
}
SQ(int y)
{
return((y)*(y));
}#define SQ(y) ((y)*(y))
main(){
int i=1;
while(i<=5)
printf("%d\n",SQ(i++));
}
在上例中函数名为SQ,形参为Y,函数体表达式为((y)*(y))。在例9.6中宏名为SQ,形参也为y,字符串表达式为(y)*(y))。 两例是相同的。例9.6的函数调用为SQ(i++),例9.7的宏调用为SQ(i++),实参也是相同的。从输出结果来看,却大不相同。分析如下:在例9.6中,函数调用是把实参i值传给形参y后自增1。 然后输出函数值。因而要循环5次。输出1~5的平方值。而在例9.7中宏调用时,只作代换。SQ(i++)被代换为((i++)*(i++))。在第一次循环时,由于i等于1,其计算过程为:表达式中前一个i初值为1,然后i自增1变为2,因此表达式中第2个i初值为2,两相乘的结果也为2,然后i值再自增1,得3。在第二次循环时,i值已有初值为3,因此表达式中前一个i为3,后一个i为4, 乘积为12,然后i再自增1变为5。进入第三次循环,由于i 值已为5,所以这将是最后一次循环。计算表达式的值为5*6等于30。i值再自增1变为6,不再满足循环条件,停止循环。从以上分析可以看出函数调用和宏调用二者在形式上相似, 在本质上是完全不同的。

6. 宏定义也可用来定义多个语句,在宏调用时,把这些语句又代换到源程序内。看下面的例子。
#define SSSV(s1,s2,s3,v) s1=l*w;s2=l*h;s3=w*h;v=w*l*h;
main(){
int l=3,w=4,h=5,sa,sb,sc,vv;
SSSV(sa,sb,sc,vv);
printf("sa=%d\nsb=%d\nsc=%d\nvv=%d\n",sa,sb,sc,vv);
}
程序第一行为宏定义,用宏名SSSV表示4个赋值语句,4 个形参分别为4个赋值符左部的变量。在宏调用时,把4 个语句展开并用实参代替形参。使计算结果送入实参之中。

文件包含

文件包含是C预处理程序的另一个重要功能。文件包含命令行的一般形式为: #include"文件名" 在前面我们已多次用此命令包含过库函数的头文件。例如:
#include"stdio.h"
#include"math.h"
文件包含命令的功能是把指定的文件插入该命令行位置取代该命令行, 从而把指定的文件和当前的源程序文件连成一个源文件。在程序设计中,文件包含是很有用的。 一个大的程序可以分为多个模块,由多个程序员分别编程。 有些公用的符号常量或宏定义等可单独组成一个文件, 在其它文件的开头用包含命令包含该文件即可使用。这样,可避免在每个文件开头都去书写那些公用量, 从而节省时间,并减少出错。

对文件包含命令还要说明以下几点:
1. 包含命令中的文件名可以用双引号括起来,也可以用尖括号括起来。例如以下写法都是允许的: #include"stdio.h" #include<math.h> 但是这两种形式是有区别的:使用尖括号表示在包含文件目录中去查找(包含目录是由用户在设置环境时设置的), 而不在源文件目录去查找; 使用双引号则表示首先在当前的源文件目录中查找,若未找到才到包含目录中去查找。 用户编程时可根据自己文件所在的目录来选择某一种命令形式。

2. 一个include命令只能指定一个被包含文件, 若有多个文件要包含,则需用多个include命令。3. 文件包含允许嵌套,即在一个被包含的文件中又可以包含另一个文件。

条件编译

预处理程序提供了条件编译的功能。 可以按不同的条件去编译不同的程序部分,因而产生不同的目标代码文件。 这对于程序的移植和调试是很有用的。 条件编译有三种形式,下面分别介绍:
1. 第一种形式:
#ifdef 标识符
程序段1
#else
程序段2
#endif
它的功能是,如果标识符已被 #define命令定义过则对程序段1进行编译;否则对程序段2进行编译。如果没有程序段2(它为空),本格式中的#else可以没有, 即可以写为:
#ifdef 标识符
程序段 #endif
#define NUM ok
main(){
struct stu
{
int num;
char *name;
char sex;
float score;
} *ps;
ps=(struct stu*)malloc(sizeof(struct stu));
ps->num=102;
ps->name="Zhang ping";
ps->sex='M';
ps->score=62.5;
#ifdef NUM
printf("Number=%d\nScore=%f\n",ps->num,ps->score);
#else
printf("Name=%s\nSex=%c\n",ps->name,ps->sex);
#endif
free(ps);
}
由于在程序的第16行插入了条件编译预处理命令, 因此要根据NUM是否被定义过来决定编译那一个printf语句。而在程序的第一行已对NUM作过宏定义,因此应对第一个printf语句作编译故运行结果是输出了学号和成绩。在程序的第一行宏定义中,定义NUM表示字符串OK,其实也可以为任何字符串,甚至不给出任何字符串,写为: #define NUM 也具有同样的意义。 只有取消程序的第一行才会去编译第二个printf语句。读者可上机试作。

2. 第二种形式:
#ifndef 标识符
程序段1
#else
程序段2
#endif
与第一种形式的区别是将“ifdef”改为“ifndef”。它的功能是,如果标识符未被#define命令定义过则对程序段1进行编译, 否则对程序段2进行编译。这与第一种形式的功能正相反。

3. 第三种形式:
#if 常量表达式
程序段1
#else
程序段2
#endif
它的功能是,如常量表达式的值为真(非0),则对程序段1 进行编译,否则对程序段2进行编译。因此可以使程序在不同条件下,完成不同的功能
#define R 1
main(){
float c,r,s;
printf ("input a number: ");
scanf("%f",&c);
#if R
r=3.14159*c*c;
printf("area of round is: %f\n",r);
#else
s=c*c;
printf("area of square is: %f\n",s);
#endif
}
本例中采用了第三种形式的条件编译。在程序第一行宏定义中,定义R为1,因此在条件编译时,常量表达式的值为真, 故计算并输出圆面积。上面介绍的条件编译当然也可以用条件语句来实现。 但是用条件语句将会对整个源程序进行编译,生成的目标代码程序很长,而采用条件编译,则根据条件只编译其中的程序段1或程序段2, 生成的目标程序较短。如果条件选择的程序段很长, 采用条件编译的方法是十分必要的。

本章小结
1. 预处理功能是C语言特有的功能,它是在对源程序正式编译前由预处理程序完成的。程序员在程序中用预处理命令来调用这些功能。

2. 宏定义是用一个标识符来表示一个字符串,这个字符串可以是常量、变量或表达式。在宏调用中将用该字符串代换宏名。

3. 宏定义可以带有参数,宏调用时是以实参代换形参。而不是“值传送”。

4. 为了避免宏代换时发生错误,宏定义中的字符串应加括号,字符串中出现的形式参数两边也应加括号。

5. 文件包含是预处理的一个重要功能,它可用来把多个源文件连接成一个源文件进行编译,结果将生成一个目标文件。

6. 条件编译允许只编译源程序中满足条件的程序段,使生成的目标程序较短,从而减少了内存的开销并提高了程序的效率。

7. 使用预处理功能便于程序的修改、阅读、移植和调试,也便于实现模块化程序设计

⑧ 预编译的编译指令

预编译指令指示了在程序正式编译前就由编译器进行的操作,可以放在程序中的任何位置。常见的预编译指令有:
(1)#include 指令
该指令指示编译器将xxx.xxx文件的全部内容插入此处。若用<>括起文件则在系统的INCLUDE目录中寻找文件,若用 括起文件则在当前目录中寻找文件。一般来说,该文件是后缀名为h或cpp的头文件。
注意:<>不会在当前目录下搜索头文件,如果我们不用<>而用把头文件名扩起,其意义为在先在当前目录下搜索头文件,再在系统默认目录下搜索。
(2)#define指令
该指令有三种用法:
第一种是定义标识,标识有效范围为整个程序,形如#define XXX,常与#if配合使用;
第二种是定义常数,如#define max 100,则max代表100(这种情况下使用const定义常数更好,原因见注1);
第三种是定义函数,如#define get_max(a, b) ((a)>(b)?(a):(b)) 则以后使用get_max(x,y)就可以得到x和y中较大的数(这种方法存在一些弊病,见注2)。
第四种是定义宏函数,如#define GEN_FUN(type) type max_##type(type a,type b){return a>b?a:b;} ,使用时,用GEN_FUN(int),则此处预编译后就变成了 max_int(int a,int b){return a>b?a:b;},以后就可以使用max_int(x,y)就可以得到x和y中较大的数.比第三种,增加了类型的说明。
(3)#if、#else和#endif指令
这些指令一般这样配合使用:
#if defined(标识) //如果定义了标识
要执行的指令
#else
要执行的指令
#endif
在头文件中为了避免重复调用(比如说两个头文件互相包含对方),常采用这样的结构:
#if !(defined XXX) //XXX为一个在你的程序中唯一的标识符,
//每个头文件的标识符都不应相同。
//起标识符的常见方法是若头文件名为abc.h
//则标识为abc_h
#define XXX
真正的内容,如函数声明之类
#endif
注1:因为:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应)。
注2:例如get_max(a++, b)时,a++会被执行多少次取决于a和b的大小!所以建议还是用内联函数而不是这种方法提高速度。虽然有这样的弊病,但这种方法的确非常灵活,因为a和b可以是各种数据类型。
注3:可以查看网络的预处理命令,编排的比较简明。

⑨ c++预处理命令有什么用

程序设计语言的预处理的概念:在编译之前进行的处理。 C语言的预处理主要有三个方面的内容: 1.宏定义; 2.文件包含; 3.条件编译。 预处理命令以符号“#”开头。
1.不带参数的宏定义:

宏定义又称为宏代换、宏替换,简称“宏”。

格式:

#define标识符 字符串

其中的标识符就是所谓的符号常量,也称为“宏名”。

预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。

掌握"宏"概念的关键是“换”。一切以换为前提、做任何事情之前先要换,准确理解之前就要“换”。

即在对相关命令或语句的含义和功能作具体分析之前就要换:

例:

#define PI 3.1415926

把程序中出现的PI全部换成3.1415926
2.带参数的宏:

除了一般的字符串替换,还要做参数代换

格式:

#define 宏名(参数表) 字符串

例如:#define S(a,b) a*b

area=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2;
二. 文件包含一个文件包含另一个文件的内容

格式:

#include "文件名"



#include <文件名>

编译时以包含处理以后的文件为编译单位,被包含的文件是源文件的一部分。

编译以后只得到一个目标文件.obj

被包含的文件又被称为“标题文件”或“头部文件”、“头文件”,并且常用.h作扩展名。

修改头文件后所有包含该文件的文件都要重新编译

头文件的内容除了函数原型和宏定义外,还可以有结构体定义,全局变量定义:

⑩ C语言中很多的预处理指令include、define等等它们各自的意义分别是什么

include的作用: #include叫做“文件包含” / include 语句包含并运行指定文件。 功能:它的功能是用来指定文件的全部内容替换程序中的命令行,从而使指定的文件与当前源文件连成一个源文件 书写格式: #include <文件名> //表示编译系统根据系统头文件存放的目录路径去搜索系统头文件,而不是在源文件目录去查找 #include "文件名" //表示编译系统首先在当前的源文件目录中查找,若未找到才根据系统的头文件存放的目录路径去搜索系统头文件 //系统定义的头文件通常使用尖括号;用户自定义的头文件通常使用双引号。 //一般来说,如果为调用库函数而用#include命令来包含相关的头文件,则用尖括号,以节约查找时间。 //如果要包含的是用户自己编写的文件(这种文件一般都在用户当前的目录中),一般用双撇号。 //若文件不在当前目录中,在双撇号内应该给出文件路径(如#include"C:\wang\file2.h") ----------------- 1.#define 的作用 在C或C++语言源程序中允许用一个标识符来表示一个字符串,称为“宏”。被定义为“宏”的标识符称为“宏名”。在编译预处理时,对程序中所有出现的“宏名”,都用宏定义中的字符串去代换,这称为“宏代换”或“宏展开”。宏定义是由源程序中的宏定义命令完成的。宏代换是由预处理程序自动完成的。 在C或C++语言中,“宏”分为有参数和无参数两种。 2. 无参宏定义 无参宏的宏名后不带参数。 其定义的一般形式为: #define 标识符 字符串 其中的“#”表示这是一条预处理命令。凡是以“#”开头的均为预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。 例如: #define M (a+b) 它的作用是指定标识符M来代替表达式(a+b)。在编写源程序时,所有的(a+b)都可由M代替,而对源程序作编译时,将先由预处理程序进行宏代换,即用(a+b)表达式去置换所有的宏名M,然后再进行编译。 程序1: #define M (a+b) main(){ int s,y; printf("input a number: "); scanf("%d",&y); s=M*M; printf("s=%d\n",s); } 上例程序中首先进行宏定义,定义M来替代表达式(a+b),在 s= M * M 中作了宏调用。在预处理时经宏展开后该语句变为: S=(a+b)*(a+b) 但要注意的是,在宏定义中表达式(a+b)两边的括号不能少。否则会发生错误。 如当作以下定义后:#difine M (a)+(b) 在宏展开时将得到下述语句:S= (a)+(b)*(a)+(b) 对于宏定义还要说明以下几点: 1. 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。 2. 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起置换。 3. 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。 3. 带参宏定义 c语言允许宏带有参数。在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。 带参宏定义的一般形式为: #define 宏名(形参表) 字符串 在字符串中含有各个形参。 带参宏调用的一般形式为: 宏名(形参表) 例如: #define M(y) ((y)*(y)+3*(y)) /*宏定义*/ .... k=M(5); /*宏调用*/ .... 在宏调用时,用实参5去代替形参y,经预处理宏展开后的语句为: k=5*5+3*5 程序2: #define MAX(a,b) (a>b)?a:b main(){ int x,y,max; printf("input two numbers: "); scanf("%d%d",&x,&y); max=MAX(x,y); printf("max=%d\n",max); } 上例程序的第一行进行带参宏定义,用宏名MAX表示条件表达式(a>b)?a:b,形参a,b均出现在条件表达式中。程序第七行max=MAX(x,y)为宏调用,实参x,y,将代换形参a,b。宏展开后该语句为: max=(x>y)?x:y; 用于计算x,y中的大数。

热点内容
兄弟连的php 发布:2025-03-19 01:24:25 浏览:809
自己做脚本可不可以 发布:2025-03-19 01:20:13 浏览:532
33的源码值 发布:2025-03-19 01:13:25 浏览:814
虚荣安卓怎么充值 发布:2025-03-19 01:12:27 浏览:892
如何更改报考密码 发布:2025-03-19 01:08:12 浏览:416
python日期类型 发布:2025-03-19 01:02:28 浏览:415
android飞机大战源码 发布:2025-03-19 00:56:52 浏览:736
javaset方法 发布:2025-03-19 00:44:21 浏览:246
淘宝上传文件夹 发布:2025-03-19 00:36:30 浏览:73
oracle数据库备份数据 发布:2025-03-19 00:35:04 浏览:547