用户登录
用户注册

分享至

define软件 头文件中#define用法

  • 作者: 华丽的承诺只是敷衍的借口i
  • 来源: 51数据库
  • 2020-04-18

#define 就是一定义宏的 工具

是在编译过程中 把程序正文中 的定义字串 替换成 被定义的字串,这样做一个方面是为了

1 程序容易阅读

2 程序修改参数方便

3 减少程序中打错字

等

可以用它来实现 常数 的定义 宏函数 其他语言的编程风格 甚至其他不伦不类的东西等

地址常数也是常数 ,只不过表示了某存储器(或端口)的位置而已

一般表示 地址使用16进制或二进制表示(任何进制都可以),

而一般常数多数使用10进制容易理解,有些也用2进制8进制或16进制

主要还是为了方便阅读

不只到你的 寄存器 是什么寄存器 硬件外设?

外设 IO 有函数 不可以直接赋值

内存的存储器可以直接赋值

cpu 的寄存器没有这种地址标识,高级语言一般也不需要关心,编译程序自动管理

不同的开发平台都有自己的软件包 控制外设,具体请参考你的开发平台的参考手册

define的用法

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中的大数。 4.防止重复定义

#define 条件编译

头文件(.h)可以被头文件或C文件包含;

重复包含(重复定义)

由于头文件包含可以嵌套,那么C文件就有可能包含多次同一个头文件,就可能出现重复定义的问题的。

通过条件编译开关来避免重复包含(重复定义)

例如

#ifndef __headerfileXXX__

#define __headerfileXXX__

„

文件内容

„

#endif

typedef和define具体的详细区别

  1. #define是编译预处理指令,在编译预处理时换,不作正确性检查,不论是否正确只进行带入替换,只有在编译已被展开的源程序时才会发现可能的错误并报错。

2.typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。

两者的区别如例:

#define A int * tepedef int * A;(这是一条语句,要加分号)

两者的作用都是将A代表int *,但是#define在预处理时进行简单的替换,而typedef不是简单替换。

typedef定义的A相当于定义了一个指针指向了int *。而#define定义的A只是进行了替换。

扩展资料:

typedef 有另外一个重要的用途,那就是定义机器无关的类型,例如,你可以定义一个叫 REAL 的浮点类型,在目标机器上它可以获得最高的精度:

typedef long double REAL;

在不支持 long double 的机器上,该 typedef 看起来会是下面这样:

typedef double REAL;

并且,在连 double 都不支持的机器上,该 typedef 看起来会是这样:

typedef float REAL;

你不用对源代码做任何修改,便可以在每一种平台上编译这个使用 REAL 类型的应用程序。唯一要改的是 typedef 本身。在大多数情况下,甚至这个微小的变动完全都可以通过奇妙的条件编译来自动实现。不是吗? 标准库广泛地使用 typedef 来创建这样的平台无关类型:size_t,ptrdiff

和 fpos_t 就是其中的例子。此外,象 std::string 和 std::ofstream 这样的 typedef

还隐藏了长长的,难以理解的模板特化语法,例如:basic_string,allocator> 和 basic_ofstream>。

参考资料:typedef-百度百科

C语言,#define语句的用法。

  1.简单的宏定义

  格式:#define 标识符 替换列表

  说明:替换列表可以是数,字符串字面量,标点符号,运算符,标识符,关键字,字符常量。

  注意:替换列表是可以为空的

  典型错误:

  #defineN=100

  inta[N];/*这样会成为inta[=100],这里会处理成为一种标识记号一样*/

  

  

  #defineN100;

  inta[N];/*带分号的定义会成为inta[100;],这是一种很常见的错误*/

  

  #definepin(int*);

  pina,b;

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

  

  

  典型的使用方法:

  使用宏定义可以自己根据自己的习惯来定义甚至改变C语言的语法习惯,例如:

#defineBEGIN{

  #defineEND}

  intmain()BEGIN

  printf("DEFINE----\n");

  END

  定义一个循环

 #defineLOOPfor(;;)

  重新定义数据类型

  #defineITint

  2.带参数的宏

  #define 标识符(x1,x2,x3...xn) 替换列表 (注意:x1,x2,x3..是宏的参数,标识符和其左括弧之间不能有空格)

  使用方法:

  #defineMAX(x,y)((x)>(y)?(x):(y))

  i=MAX(j+k,m-n);

  替换为:

  i=MAX((j+k)>(m-n)?(j+k):(m-n));

  #defineSI_EX(n)((n)%2==0)

  if(SI_EX(i))i++;

  替换为:

 if(SI_EX((i)%2==0))

  通过以上例子可以看出,标识符带参数(X1,X2,X3.....)在替换时会被替换列表(Y1,Y2,Y3....)对应的替换,但是和顺序无关。

  

  3.宏的特殊单行定义

  #defineA(x)T_##x

  #defineB(x)#@x

  #defineC(x)#x

  x=1

  替换为:

  A(1)------> T_1 (T_##x,##符号是记号粘黏符号,将前后的字符粘黏起来。)

  B(1)------> '1' ( #@x , #@ 符号会将宏的参数进行字符串字面量化,并且加‘’号)

  C(1)------> "1" ( #x ,#符号会将宏的参数进行字符串字面量化,并且加""号)

  

  4.define的多行定义

  define可以替代多行的代码,在每一个换行的时候加上一个"\"

 #defineMAX(X,Y)do{\

  语句1;\

  语句2;\

  /*注释的写法*/\

  }while(0)/*(notrailing;)*/\

  

  

  5.在大规模的开发过程中,特别是跨平台和系统的软件里,define最重要的功能是条件编译。

  #ifdefWINDOWS

  ......

  ......

  #endif

  #ifdefLINUX

  ......

  ......

  #endif

  可以在编译的时候通过#define设置编译环境

  6.取消宏

  #undef标识符

  7.条件编译

  #ifdefXXX…(#else)…#endif

  8.预定义宏

  在C语言中收录了一些有用的宏,这些宏是提供当前编译信息的。

  __LINE__ 被编译文件的行数

  (整型)

  __FILE__ 被编译文件的名字 (字符型)

  __DATE__ 编译日期 (字符型)

  __TIME__ 编译时间 (字符型)

  __STDC__ 如果编译器接受标准C,那么值为1. (整型)

  

  通常在编译的时候可以用这些预定义的宏来进行排错,例如:

  一般情况下,当出现除零的情况时编译器是没有提示的,可以自定义一个解决办法。

  #defineCHECKZERO(divisor)\

  if(divisor==0)\

  printf("***ATTEMPTTODIVIDEBYZEROINLINE%doffile%s***\n",__LINE__,__FILE__);\

  引用方法

  CHECKZERO(j);

  k=i/j;

const和define的区别

  define宏定义和const常变量区别:

  1.define是宏定义,程序在预处理阶段将用define定义的内容进行了替换。因此程序运行时,常量表中并没有用define定义的常量,系统不为它分配内存。

  const定义的常量,在程序运行时在常量表中,系统为它分配内存。

  2.define定义的常量,预处理时只是直接进行了替换。所以编译时不能进行数据类型检验。

  const定义的常量,在编译时进行严格的类型检验,可以避免出错。

  3.define定义表达式时要注意“边缘效应”,例如如下定义:

  #define N 2+3 //我们预想的N值是5,我们这样使用N

  int a = N/2; //我们预想的a的值是2.5,可实际上a的值是3.5

头文件中的ifndef/define/endif什么用处?

ifndef和endif是一对条件预编译语句,给你一个例子:

ifndef abc;//意思是如果没有定义abc这个特征符,则编译之后到endif之前的语句否则略过

//define abc;这条语句;

define abc;

endif;

比如有一段代码,有时需要根据需要不进行编译或进行编译,如以下代码:

ifdef abc;

某段代码;

endif;

意思就是如果程序中定义了abc特征符,则编译这里所说的"某段代码”,否则不进行编译,

如果程序是这样:

ifndef abc;

define abc;

endif;

ifdef abc;

某段代码;

endif;

则这里所说的“某段代码”肯定会被编译,因为在设计程序之初,可能需要根据某个条件来决定是否编译“某段代码”,但是后来发现,这样的条件编译已经没有必要,而且必须要编译“某段代码”,两种办法,一种是把ifdef abc和endif;去掉;另一种就像这里一样,在

ifdef abc;

某段代码;

endif;

之前加

ifndef abc;

define abc;

endif;

一般在一个应用开发体系中,功能的真正逻辑实现是以硬件层为基础,在驱动程序、功能层程序以及用户的应用程序中完成的。头文件的主要作用在于多个代码文件全局变量(函数)的重用、防止定义的冲突,对各个被调用函数给出一个描述,其本身不需要包含程序的逻辑实现代码,它只起描述性作用,用户程序只需要按照头文件中的接口声明来调用相关函数或变量,链接器会从库中寻找相应的实际定义代码。(eg.C++编译模式[1])

从以上结构图来看,头文件是用户应用程序和函数库之间的桥梁和纽带。在整个软件中,头文件不是最重要的部分,但它是C语言家族中不可缺少的组成部分。编译时,编译器通过头文件找到对应的函数库,进而把已引用函数的实际内容导出来代替原有函数。进而在硬件层面实现功能。

从以上例子可以看出,头文件一般由四部分内容组成:(1)头文件开头处的版权和版本声明;(2)预处理块;(3)inline函数的定义;(4)函数和类结构声明等。在头文件中,用 ifndef/define/endif结构产生预处理块,用 #include 格式来引用库的头文件。头文件的这种结构,是利用C语言进行开发软件所通常具备的,属于公有知识。

【keil c51 uvision3 软件里面】#define语句 后面的int unsigned auto 关键字颜色不变化,为什么??

如楼上所述,#define是宏定义,所以关键字不会变颜色,

如果你想自己改变颜色,那么就点击菜单上的Edit——configuration选项——Colors&Fonts——再点EditCFile——找到Keyword,在右边Foreground下拉按钮选择你所想要的颜色,最后OK!

请问头文件中的 ifndef/define/endif 干什么用?

在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误。在头文件中实用#ifndef #define #endif能避免头文件的重定义。

方法:例如要编写头文件test.h

在头文件开头写上两行:

#ifndef _TEST_H

#define _TEST_H//一般是文件名的大写

头文件结尾写上一行:#endif这样一个工程文件里同时包含两个test.h时,就不会出现重定义的错误了。

分析:当第一次包含test.h时,由于没有定义_TEST_H,条件为真,这样就会包含(执行

)#ifndef _TEST_H和#endif之间的代码,当第二次包含test.h时前面一次已经定义了_TEST_H,条件为假,#ifndef _TEST_H和#endif之间的代码也就不会再次被包含,这样就避免了重定义了。主要用于防止重复定义宏和重复包含头文件

转载请注明出处51数据库 » define软件 头文件中#define用法

软件
前端设计
程序设计
Java相关