C语言中define与const的用法区别分析

题目:

 代码如下 复制代码

#define N 2
#define M N+1
#define NUM 2*M+1
main( )
{ int i;
for(i=1;i<=NUM;i++) printf(“%dn”,i);
}

该程序中的for循环执行的次数是( )
A) 5 B) 6 C) 7 D) 8

答案是6,跑过以后怎么都不理解,这是因为忽略了#define的重大不同。

#define进行的其实是简单的代入, 换句话说,NUM去找了M的表达式,把M的表达式代入,得出2*N+1+1,接着再去找N是多少,结果是2*2+1+1,因此等于6,而变量的话,毫无疑问则是进行了运算之后得出了的结果。

补充

1.简单的define定义

 代码如下 复制代码

#define MAXTIME 1000

一个简单的MAXTIME就定义好了,它代表1000,如果在程序里面写

if(i<MAXTIME){.........}

编译器在处理这个代码之前会对MAXTIME进行处理替换为1000。

这样的定义看起来类似于普通的常量定义CONST,但也有着不同,因为define的定义更像是简单的文本替换,而不是作为一个量来使用,这个问题在下面反映的尤为突出。

2.define的“函数定义”

define可以像函数那样接受一些参数,如下

 代码如下 复制代码

#define max(x,y) (x)>(y)?(x):(y);

这个定义就将返回两个数中较大的那个,看到了吗?因为这个“函数”没有类型检查,就好像一个函数模板似的,当然,它绝对没有模板那么安全就是了。可以作为一个简单的模板来使用而已。

但是这样做的话存在隐患,例子如下:

 代码如下 复制代码
#define Add(a,b) a+b;

在一般使用的时候是没有问题的,但是如果遇到如:c * Add(a,b) * d的时候就会出现问题,代数式的本意是a+b然后去和c,d相乘,但是因为使用了define(它只是一个简单的替换),所以式子实际上变成了
c*a + b*d

另外举一个例子:

 代码如下 复制代码
#define pin (int*);
pin a,b;

本意是a和b都是int型指针,但是实际上变成int* a,b;
a是int型指针,而b是int型变量。
这是应该使用typedef来代替define,这样a和b就都是int型指针了。

所以我们在定义的时候,养成一个良好的习惯,建议所有的层次都要加括号。

3.宏的单行定义

 代码如下 复制代码

#define A(x) T_##x
#define B(x) #@x
#define C(x) #x

我们假设:x=1,则有:

A(1)------〉T_1
B(1)------〉'1'
C(1)------〉"1"

(这里参考了 hustli的文章)

3.define的多行定义

define可以替代多行的代码,例如MFC中的宏定义(非常的经典,虽然让人看了恶心)

 代码如下 复制代码
#define MACRO(arg1, arg2) do { /
/* declarations */ /
stmt1; /
stmt2; /
/* ... */ /
} while(0) /* (no trailing ; ) */

关键是要在每一个换行的时候加上一个"/"

时间: 2024-10-10 08:56:53

C语言中define与const的用法区别分析的相关文章

c-C语言中#define的问题

问题描述 C语言中#define的问题 我在学CUDA的时候看到库文件driver_type.h中的一个定义 typedef device_builtin enum cudaError cudaError_t; 看不懂这是什么意思. cudaError_t是新定义类型. cudaError的定义是:enum device_builtin cudaError{...} device_builtin是: #define device_builtin 我不明白这里的__device_builtin__

C语言中char*和char[]用法区别分析_C 语言

本文实例分析了C语言中char* 和 char []的区别.分享给大家供大家参考之用.具体分析如下: 一般来说,很多人会觉得这两个定义效果一样,其实差别很大.以下是个人的一些看法,有不正确的地方望指正. 本质上来说,char *s定义了一个char型的指针,它只知道所指向的内存单元,并不知道这个内存单元有多大,所以: 当char *s = "hello";后,不能使用s[0]='a':语句进行赋值.这是将提示内存不能为"written". 当用char s[]=&q

C语言中NSInteger,NSNumber以及Int的区别

NSInteger和NSNumber   首先:NSInteger,NSNumber并没有什么关系,更不要想当然的以为二者还有什么继承关系,甚至还有人问NSInteger是不是NSNumber的子类?答案当然是NO!!!NSInteger只是一个基本的数据类型,而NSNumber是OC的对象,并且NSNumber继承自NSValue,NSValue又继承自NSObject. 既然 NSInteger是基本类型,那么,使用起来就非常简单. 声明一个变量, NSInteger myInt: 直接赋值

Go语言中struct的匿名属性特征实例分析_Golang

本文实例分析了Go语言中struct的匿名属性特征.分享给大家供大家参考.具体分析如下: Go语言中struct的属性可以没有名字而只有类型,使用时类型即为属性名.(因此,一个struct中同一个类型的匿名属性只能有一个) 复制代码 代码如下: type PersonC struct {      id      int      country string  }    //匿名属性  type Worker struct {      //如果Worker有属性id,则worker.id表示

PHP中exec与system用法区别分析_php技巧

本文实例讲述了PHP中exec与system用法区别,分享给大家供大家参考之用.具体方法如下: 一般来说,在PHP中调用外部命令,可以用exec及system来实现: system() 原型:string system (string command [, int return_var]) system()函数很其它语言中的差不多,它执行给定的命令,输出和返回结果.第二个参数是可选的,用来得到命令执行后的状态码. 返回结果: 成功返回0,   失败(命令不存在等原因)   返回   非0值 ex

C语言中Static和Const关键字的的作用

程序的局部变量存在于(堆栈)中,全局变量存在于(静态区 )中,动态申请数据存在于( 堆)中. 1.作用于变量: 用static声明局部变量-------局部变量指在代码块{}内部定义的变量,只在代码块内部有效(作用域),其缺省的存储方式是自动变量或说是动态 存储的,即指令执行到变量定义处时才给变量分配存储单元,跳出代码块时释放内存单元(生命期).用static声明局部变量时,则改变变量的存储方式(生 命期),使变量成为静态的局部变量,即编译时就为变量分配内存,直到程序退出才释放存储单元.这样,使

简介Go语言中的select语句的用法_Golang

在Go编程语言中的select语句的语法如下: 复制代码 代码如下: select {     case communication clause  :        statement(s);          case communication clause  :        statement(s);     /* you can have any number of case statements */     default : /* Optional */        stat

C语言中while /do while语句用法

C语言while语句的用法 while语句的一般形式为:while(表达式)语句 其中表达式是循环条件,语句为循环体. while语句的语义是:计算表达式的值,当值为真(非0)时, 执行循环体语句.其执行过程可用下图表示. [例6.2]用while语句计算从1加到100的值.用传统流程图和N-S结构流程图表示算法  代码如下 复制代码 main() {    int i,sum=0;    i=1;    while(i<=100)         { sum=sum+i;          

C语言中#define与typedef的互换细节详解_C 语言

复制代码 代码如下: #include <stdio.h>/*<---------           #define    string    char *            ---->*/typedef   char *   string;       int main(void){   string   a[] = {"I", "like", "to", "fight,"},   b[] =