楼主我还是给你说个不使用#define和const的其他方案吧,其实各种方案都是有一定的适用范围的,不可能面面俱到,否则其他的根本就没有用武之地了。
#define,最简单,直接宏替换,是C/C++与处理的一部分,不是C/C++语言本身,对程序的结果没有任何影响。宏定义太深的话,只对编译过程有影响,使得编译变慢。
const:它的含义其实被这个名字蒙蔽了,const修饰的根本不是常量,而是只读量。const修饰的内容其实是可以改变的,不信的话直接强制转换成非const类型再赋值。这是因为const类型是需要分配内存的,内存是可以修改的。各种分配到flash的扩展这里不讨论,仅仅针对C/C++语言。
enum:这个东西基本满足你所说的所有要求,不占用内存、Flash,会执行类型检查,而且没有#define的各种副作用。但是局限也很明显,就是定义的只能是整数。
inline:这个很强悍的,用用就知道了。C++支持,ANSI C并不支持,AVR C中这个属于C语言的扩展得以支持,其他的编译器有的用__iinline,支持GCC的都可以通过__attribute__((inline))来支持内联。inline是内联函数,因此能做很多事情,但是程序量太大的话,产生的效果可能并不是你所需要的;如果仅仅是常数的话,建议你可以使用一下。缺点:使得程序代码量变长。
模板:C++专用,只用C的话请忽略。模板可以直接进行编译期计算,注意,是计算,不是#define之类的预处理。但是是在编译期,不是运行期,对程序的最终结果没有影响,编译过程则会大量减慢速度。编写过程很麻烦的。
举个例子:
分别表示这么几个常量,100、100.0、100+200、整数N、整数N阶乘(其中N可以在程序中替换)
宏定义:#define v1 100 #define v2 100.0 #define v3 (100+200) #define v4(N) N #define v5(N) fact(N)
const: const unsigned char v1 = 100; const float v2 = 100.0; const int v3 = 100 + 200; 无法实现 无法实现
enum: enum {v1 = 100}; 无法实现 enum{v3=100+200}; 无法实现 无法实现
inline: inline unsigned char v1(){ inline float v2(){ inline int v3(){ inline int v4(int N){ inline int v5(int N){
return 100; return 100.0; return 100 + 200; return N; return (N==0)?1: N * v5(N - 1);
} } } } }
模板(配合enum,只能用于C++):
template<> template<> 同第一个 template 内容太多,详见下面
struct v1 { struct v2 { struct v4{
enum{ value = 100; } static const float value = 100.0; enum{ value = N; }
}; }; }
模板调用:v1::value v2::value v4<10>::value
对于编译期常量计算(比如递归啊,开方啊,对数啊,计算三角函数啊什么的),都只能通过模板的特化来完成。其他方案都必须调用函数,占用大量的Flash空间,而编译期常量计算是在编译器完成的,编译完之后会形成常量,不会占用Flash,但是会大大增加编译的时间。
下面是一个对整数N阶乘的编译期运算,那么老长的代码,编译后的结果也许只有一条指令。
template
struct fact{
enum {value = N * fact< N - 1>};
};
//下面是特化:
template <>
struct fact<0> {
enum {value = 1};
};
调用:5的阶乘:fact<5>::value,8的阶乘:fact<8>::value,...
各种方案的优劣性请自行试验,本人只是手写了,没有经过验证。