嵌入式知识点学习篇四(C\C++)

预处理器标识#error的目的是什么?

#error预处理指令的作用是,编译程序时,只要遇到#error就会生成一个编译错误提示消息,并停止编译。其语法格式为:#error error-message。

下面举个例子:
程序中往往有很多的预处理指令

#ifdef XXX …
#else
#endif

当程序比较大时,往往有些宏定义是在外部指定的(如makefile),或是在系统头文件中指定的,当不太确定当前是否定义了 XXX 时,就可以改成如下这样进行编译:

#ifdef XXX …
#error “XXX has been defined”
#else
#endif

这样,如果编译时出现错误,输出了XXX has been defined,表明宏XXX已经被定义了。

定义常量谁更好?#define还是const?

define与 const都能定义常量,效果虽然一样,但是各有侧重。

define既可以替代常数值,又可以替代表达式,甚至是代码段,但是容易出错,而 const的引入可以增强程序的可读性,它使程序的维护与调试变得更加方便。具体而言,它们的差异主要表现在以下3个方面。

  1. define只是用来进行单纯的文本替换, define常量的生命周期止于编译期不分配内存空间,它存在于程序的代码段,在实际程序中,它只是一个常数;而 const常量存在于程序的数据段,并在堆栈中分配了空间, const常量在程序中确确实实存在,并且可以被调用、传递。
  2. const常量有数据类型,而 define常量没有数据类型。编译器可以对 const常量进行类型安全检
    査,如类型、语句结构等,而 define不行。
  3. 很多IDE支持调试 const定义的常量,而不支持 define定义的常量由于 const修饰的变量可以排除程序之间的不安全性因素,保护程序中的常量不被修改,而且对数据类型也会进行相应的检查,极大地提高了程序的健壮性,所以一般更加倾向于用const来定义常量类型

typedef和define有什么区别?

typedef 与 define 都是替一个对象取一个别名,以此来增强程序的可读性,但是它们在使用和作用上也
存在着以下4个方面的不同。

  1. 原理不同

#define是C语言中定义的语法,它是预处理指令,在预处理时进行简单而机械的字符串替换,不做正确性检査,不管含义是否正确照样代入,只有在编译已被展开的源程序时,才会发现可能的错误并报错。例如, # define Pl 3.1415926 ,当程序执行 area=PI*r*r 语句时,PI会被替换为3.1415926。于是该
语句被替换为 area=3.1415926*r*r 。如果把# define语句中的数字9写成了g,预处理也照样代入,而不去检查其是否合理、合法。

typedef是关键字,它在编译时处理,所以 typedef具有类型检查的功能。它在自己的作用域内给一个已经存在的类型一个别名,但是不能在一个函数定义里面使用标识符 typedef。例如, typedef int INTEGER; ,这以后就可用 INTEGER来代替int作整型变量的类型说明了,例如: INTEGER a,b;

用 typedef定义数组、指针、结构等类型将带来很大的方便,不仅使程序书写简单而且使意义更为明确,因而增强了可读性。例如: typedef int a[10];表示a是整型数组类型,数组长度为10。然后就可用a说明变量,例如:语句a s1,s2;完全等效于语句 int s1[10],s2[10]。同理, typedef void(*p)(void)表示p是一种指向void型的指针类型。

  1. 功能不同

typedef用来定义类型的别名,这些类型不仅包含内部类型(int、char等),还包括自定义类型(如struct),可以起到使类型易于记忆的功能。

例如: typedef int (*PF)(const char *, const char*);
定义一个指向函数的指针的数据类型PF,其中函数返回值为int,参数为 const char*。typedef还有另外一个重要的用途,那就是定义机器无关的类型。例如,可以定义一个叫REAL的浮点类型,在目标机器上它可以获得最高的精度: typedef long double REAL; ,在不支持 long double的机器上,该 typedef看起来会是下面这样: typedef double REAL; ,在 double都不支持的机器上,该 typedef看起来会是这样: typedef float REAL;

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

  1. 作用域不同

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

程序示例如下:

void fun()
{
	#define A int
}

void gun()
{
	//这里也可以使用A,因为宏替换没有作用域,但如果上面用的是 typedef,那这里就不能用
	//A,不过,一般不在函数内使用 typedef
}
  1. 对指针的操作不同

两者修饰指针类型时,作用不同。

#define INTPTR1 int*
typedef int* INTPTR2;
INTPTR1 p1,p2;
INTPTR2 p3,p4;

INTPTR1 p1, p2和INTPTR2 p3, p4的效果截然不同。 INTPTR1 p1, p2进行字符串替换后变成int*p1,p2 ,要表达的意义是声明一个指针变量p1和一个整型变量p2.而 INTPTR2 p3,p4,由于INTPTR2是具有含义的,告诉我们是一个指向整型数据的指针,那么p3和p4都为指针变量,这句相当于int*pl,*p2 。从这里可以看出,进行宏替换是不含任何意义的替换,仅仅为字符串替换;而用 typedef为一种数据类型起的别名是带有一定含义的。

程序示例如下:

#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指向的内容,但是p1可以指向其他内容。而对于 const INTPTR2 p2,由于 INTPTR2表示的是个指针类型,因此用 const去限定,表示封锁了这个指针类型,因此p2是一个指针常量,不可使p2再指向其他内容,但可以通过p2修改其当前指向的内容。 INTPTR2 const p3同样声明的是一个指针常量。

如何使用define声明一个常数,用以表明一年中有多少秒?(忽略闰年问题)

#define SECOND_PER_YEAR (606024*365)UL

#include <filename.h> 和 #include “filename.h” 有什么区别?

对于 include< filename. h>,编译器先从标准库路径开始搜索 filename.h,使得系统文件调用较快。

对于# include“ filename.h"”,编译器先从用户的工作路径开始搜索 filename.h,然后去寻找系统路径,使得自定义文件较快。

头文件的作用有哪些?

头文件的作用主要表现为以下两个方面:

  1. 通过头文件来调用库功能。出于对源代码保密的考虑,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口是怎么实现的。编译器会从库中提取相应的代码。
  2. 头文件能加强类型安全检查。当某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,大大减轻程序员调试、改错的负担。

在头文件中定义静态变量是否可行,为什么?

不可行,如果在头文件中定义静态变量,会造成资源浪费的问题,同时也可能引起程序错误。因为如果在使用了该头文件的每个C语言文件中定义静态变量,按照编译的步骤,在每个头文件中都会单独存在一个静态变量,从而会引起空间浪费或者程序错误。所以,不推荐在头文件中定义任何变量,当然也包括静态变量。

写一个“标准”宏MIN,这个宏输入两个参数并返回较小的一个?

#define MIN(A,B) ( (A) <= (B) ? (A) : (B) )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值