jam*_*lin 25
作为0A0D提到的,还有#defines,enums和const变量.值得注意的是,const合格变量在C中不被认为是编译时常量,因此在某些情况下不能使用(例如,在声明数组的大小时).
enum但是,常量是编译时常量.对于积分值,IMO通常更喜欢优先enums于const变量#define.
小智 18
实际上有三种方法来定义这些常量,
在C中,除非另有说明,否则一切都是int.当我有许多相关的整数常量时,我更喜欢枚举.当您不关心值是什么时,枚举显然更可取.但即使你确实需要为所有常量指定值,我也喜欢枚举的心理分组.当您拥有类型时,代码文档本身会更好,例如
Error MyFunc();
Run Code Online (Sandbox Code Playgroud)
清楚地返回一组特定的错误代码,而
int MyFunc()
Run Code Online (Sandbox Code Playgroud)
可能会返回Unix errno的#define'd列表中的一个,或者可能是其他东西,或者那些加上一些特殊值 - 谁知道呢?如果您有多组返回代码,此功能使用哪一组?
更具体的枚举类型名称有助于编辑器中的标签工具,greps,调试等.
严格的lint可能会给你一些关于使用枚举作为整数的警告,例如,如果你添加或者它们,或者将枚举传递给int.
const对象不同于枚举或#define,特别是在C中.在ANSI C中,const int占用空间就像常规int一样; 大多数编译器也会生成指向此地址的指针,而不是内联值.因此,我很少在C中使用const int.(C++的语义略有不同,因此选择不同.)
我曾经使用的每个编译器都可以选择在尽可能小的空间中存储枚举.通常它甚至是默认选项.要在使用这样的选项时强制使用更宽的枚举,我通常会抛出一个额外的无符号值:
typedef enum
{
MyEnumA,
MyEnumB,
MyEnumForce16 = 7fff
} MyEnum;
Run Code Online (Sandbox Code Playgroud)
枚举常量(enum)的使用与使用#define的传统符号常量样式相比具有许多优点.这些优点包括较低的维护要求,改进的程序可读性和更好的调试能力.
1)第一个优点是枚举常量由编译器自动生成.相反,符号常量必须由程序员手动赋值.
例如,如果您的程序中可能出现错误代码的枚举常量类型,那么您的枚举定义可能如下所示:
enum Error_Code
{
OUT_OF_MEMORY,
INSUFFICIENT_DISK_SPACE,
LOGIC_ERROR,
FILE_NOT_FOUND
};
Run Code Online (Sandbox Code Playgroud)
在前面的示例中,编译器会自动为OUT_OF_MEMORY分配值0(零),因为它首先出现在定义中.然后编译器继续自动为枚举常量赋值,使INSUFFICIENT_DISK_SPACE等于1,LOGIC_ERROR等于2,FILE_NOT_FOUND等于3,依此类推.如果您通过使用符号常量来接近相同的示例,您的代码将如下所示:
#define OUT_OF_MEMORY 0
#define INSUFFICIENT_DISK_SPACE 1
#define LOGIC_ERROR 2
#define FILE_NOT_FOUND 3
Run Code Online (Sandbox Code Playgroud)
两种方法中的每一种都得到相同的结果:四个常量分配数值来表示错误代码.但是,如果要添加两个常量来表示错误代码DRIVE_NOT_READY,请考虑所需的维护CORRUPT_FILE.使用枚举常量方法,您只需将这两个常量放在枚举定义中的任何位置即可.编译器将为这些常量生成两个唯一值.使用符号常量方法,您必须手动为这些常量分配两个新数字.此外,您需要确保为这些常量指定的数字是唯一的.
2)使用枚举常量方法的另一个好处是,您的程序更具可读性,因此可能需要稍后更新程序的其他人可以更好地理解这些程序.
3)使用枚举常量的第三个好处是某些符号调试器可以打印枚举常量的值.相反,大多数符号调试器无法打印符号常量的值.这对于调试程序来说是一个巨大的帮助,因为如果你的程序在使用枚举的行停止,你可以简单地检查该常量并立即知道它的值.另一方面,由于大多数调试器无法打印#define值,因此您很可能必须通过在头文件中手动查找来搜索该值.
该#define语句是预编译器指令.从技术上讲,任何以#开头的行都是预编译器可以执行的操作.预编译器将使用其定义替换定义的标记的所有实例.这样做:
#define DELAY 40
for (i=0;i<DELAY;i++) {
for (j=0;j<DELAY;j++) {
asm NOP;
}
}
Run Code Online (Sandbox Code Playgroud)
与此完全相同(就编译器而言):
for (i=0;i<40;i++) {
for (j=0;j<40;j++) {
asm NOP;
}
}
Run Code Online (Sandbox Code Playgroud)
当编译器生成机器代码时,它将看到数字40并使用立即寻址模式以便与累加器进行比较.数字40将在您引用时多次存储在代码中.在这种情况下,它是两次.这是CodeWarrior Ver5生成的程序集:
7: char i,j;
8: for (i=0;i<DELAY;i++) {
0002 95 [2] TSX
0003 7f [2] CLR ,X
0004 [5] L4:
9: for (j=0;j<DELAY;j++) {
0004 6f01 [3] CLR 1,X
0006 [5] L6:
10: asm NOP;
0006 9d [1] NOP
0007 6c01 [4] INC 1,X
0009 e601 [3] LDA 1,X
000b a128 [2] CMP #40 ;<---- notice opcode a1 and immediate constant 40, which is $28 in hexadecimal
000d 25f7 [3] BCS L6
000f 7c [3] INC ,X
0010 f6 [2] LDA ,X
0011 a128 [2] CMP #40 ;<---- and here it is again.
0013 25ef [3] BCS L4
11: }
12: }
13: }
Run Code Online (Sandbox Code Playgroud)
Ash*_*unn 17
常量允许您指定数据类型,这通常是一个优势.宏更灵活,因此如果你不小心,可能会让你更麻烦.
最佳实践是尽可能使用常量,并且仅在您确实需要宏时使用#define,而不仅仅是命名的文字值.
| 归档时间: |
|
| 查看次数: |
17788 次 |
| 最近记录: |