C #定义vs常量全局
执行以下操作之间有什么区别:C #定义vs常量全局,c,c-preprocessor,C,C Preprocessor,执行以下操作之间有什么区别: const int var1=100; #define var2 200 int main(int argc, char* argv[]) { } var2是否占用地址/值,还是由编译器替换?在您的示例中,var2只是由C预处理器替换的文本。在编译程序之前,预处理器解析源文件并用扩展文本替换任何出现的“var2”(不在注释或字符串文本中),在您的示例中,扩展文本是数字200。它不会占用内存空间,因为编译器甚至看不到“var2”,它只看到数值常量文本“20
const int var1=100;
#define var2 200
int main(int argc, char* argv[])
{
}
var2
是否占用地址/值,还是由编译器替换?在您的示例中,var2
只是由C预处理器替换的文本。在编译程序之前,预处理器解析源文件并用扩展文本替换任何出现的“var2”(不在注释或字符串文本中),在您的示例中,扩展文本是数字200
。它不会占用内存空间,因为编译器甚至看不到“var2”,它只看到数值常量文本“200”
然而,var1
是一个不可修改的左值(即它确实存在于内存中)。当您使用关键字const
限定变量定义时,每当程序试图修改变量时,编译器都会抛出错误
使用像#define var2 200这样的宏确实有性能优势-即程序占用的内存更少(因为堆栈上的变量更少),程序运行速度可能会快一点(也许可以忽略不计)(因为处理器不必总是从内存中加载值)
但是,宏可能容易出错,而且,除了在性能最为密集的应用程序中,使用const
变量的保护措施通常会超过成本。不过,今天的编译器非常智能,可以对const
变量执行优化,以进一步降低性能成本。在您的示例中,var2
只是一个文本,将由C预处理器代替。在编译程序之前,预处理器解析源文件并用扩展文本替换任何出现的“var2”(不在注释或字符串文本中),在您的示例中,扩展文本是数字200
。它不会占用内存空间,因为编译器甚至看不到“var2”,它只看到数值常量文本“200”
然而,var1
是一个不可修改的左值(即它确实存在于内存中)。当您使用关键字const
限定变量定义时,每当程序试图修改变量时,编译器都会抛出错误
使用像#define var2 200这样的宏确实有性能优势-即程序占用的内存更少(因为堆栈上的变量更少),程序运行速度可能会快一点(也许可以忽略不计)(因为处理器不必总是从内存中加载值)
但是,宏可能容易出错,而且,除了在性能最为密集的应用程序中,使用const
变量的保护措施通常会超过成本。不过,今天的编译器非常智能,可以对常量
变量执行优化,以进一步降低性能成本。除非您在var1
上使用操作符的&
地址,否则编译器没有义务给它一个固定地址。(如果变量是用外部链接定义的,则可能会这样做。)
即使您使用var1
s地址,编译器也有权用已知值替换对变量的引用。因此,在运行时,定义常量的两种方法之间没有真正的区别
在编译过程中,有一个区别:var2
可以用于编译器需要常量的地方,例如大小写标签或数组大小,而var1
不能。这对性能没有影响,但可能仍然需要考虑
此外,整数文字(如果使用的话)必须存储在某个地方,即使它是机器指令的直接操作数。这是否可行和有益取决于整数的大小和机器架构。它不取决于常量是否有名称。除非您在var1
上使用运算符的&
地址,否则编译器没有义务给它一个固定地址。(如果变量是用外部链接定义的,则可能会这样做。)
即使您使用var1
s地址,编译器也有权用已知值替换对变量的引用。因此,在运行时,定义常量的两种方法之间没有真正的区别
在编译过程中,有一个区别:var2
可以用于编译器需要常量的地方,例如大小写标签或数组大小,而var1
不能。这对性能没有影响,但可能仍然需要考虑
此外,整数文字(如果使用的话)必须存储在某个地方,即使它是机器指令的直接操作数。这是否可行和有益取决于整数的大小和机器架构。它不取决于常量是否有名称。var2
在代码到达compiler@NateEldredge谢谢,这是一个有用的链接。但我并不真正理解公认的答案,例如:const在C中并不意味着某个东西是常量。它只是意味着变量是只读的。
只读不意味着某些东西是常量吗?或者这仅仅意味着它可能不是常量,但对于这个程序来说只是只读的?@samuelbrody1249:我认为它们的意思是“常量”,即“编译时已知的值”。您可以拥有extern const int foo
在这种情况下,编译器不知道foo
的值,并且无论何时读取其值,都会生成内存访问,就像任何其他变量一样(禁止链接时间优化等)。如果您试图以一种明显的方式写入foo
,编译器只会生成一个诊断。var2
在代码到达编译之前被预处理器替换