什么时候const被认为是一个常量?
在阅读stackoverflow中的一些问题和答案时,我遇到了这个问题
我试图理解它,但答案很难理解,特别是像这样的术语
-
静态存储持续时间
-
在翻译阶段无法评估表达式
等等…
此外,我认为常量总是常量(这是我从学校学到的)
有人可以让它有点容易理解吗?
这里有两个几乎完全不相关的概念:
- “常量表达式”是可以在编译时运行的代码。
-
4+5
是常量表达式。 -
const A=4;
有时在某些上下文中使A
成为常量表达式,因为它是const
并从常量表达式4
初始化。 (这仅适用于C ++,而不适用于C) -
B=A;
A
本身可以是常量表达式,但B
是变量,并且本身可能不是常量表达式。
-
-
const
变量是函数(或结构)承诺不会改变的变量,尽管其他东西可能会改变同一个变量。
在C(与C ++不同)中,只有当表达式中的每个值都是数字常量或枚举值的名称时,算术表达式才是“常量表达式”。 也就是说,虽然您可能已将变量声明为static const int
,但您仍然无法在常量算术表达式中使用该(常量)变量。
请注意,“常量表达式”是由定义C语言的正式标准定义的短语。 还有其他表达式直观地保持不变,但它们不包含在正式定义中。
具有“静态存储持续时间”的变量只是在整个程序执行期间存在的变量。 大多数这样的变量是全局变量(即不是任何函数的一部分,甚至不是main
),但在C和C ++中,你可以在函数范围内有一个static
变量。 这样的变量只初始化一次,无论调用函数多少次,它都只存在一个实例。
全局变量和具有静态存储持续时间的其他变量只能根据上述定义初始化为常量表达式。 无论它们是否是const
变量,都是这种情况。 问题只是变量具有静态存储持续时间,这意味着必须在程序执行之前初始化它们。 (在程序执行过程中存在一个具有静态存储持续时间的变量,因此如果它被初始化 – 也就是说,给定一个初始值,而不是在程序执行期间分配一个值 – 初始化必须在程序执行之前进行执行)。
在C ++中,声明为static const
的变量被认为是一个常量值,因此它可以出现在常量表达式中。 但是,在C中,情况并非如此,因此C编译器不需要跟踪static const
变量的初始值。
你被const
和constant
const
糊涂了。
const
decorator修饰一个变量,它必须有一个内存位置。(但对于register
并不是必需的。)它主要向人类和编译器显示该变量的值不应该被改变。
constant
是编译器知道其含义的表达式。
所以,如果你这样做:
const float PI = 3.14;
在文件范围内,它将分配内存并具有static storage duration
,其基本上与进程具有相同的生命周期。
但如果你这样做:
#define PI2 (3.14)
这是一个不同的故事,因为没有内存将包含此信息。
所以,如果你写:
float foo1 = 2 * PI; float foo2 = 2 * PI2;
您可以确定foo2
将在编译后直接分配到6.28
,而foo1
是否如此是实现定义的,因为它实际上取决于称为常量替换的优化技能。
在C中, const
-qualified变量与常量不同 。 整数文字50
和100
是常量表达式; 它们的值在编译时是已知的(也就是说,它们可以在转换阶段进行评估,这意味着当编译器将源代码转换为机器代码时)。 但是, 变量 a
, c
和d
在运行时1之前不会设置它们的值; 这意味着它们不能在需要编译时常量2的上下文中使用(在转换阶段无法对它们进行评估)。 所有const
限定符都告诉编译器拒绝任何在初始化后尝试修改这些变量的代码。
链接问题中的问题是endX
和endY
在任何函数之外的文件范围内声明。 因此,变量具有静态存储持续时间 ,这意味着当程序首次加载到内存中时, 在main
执行之前 ,保留它们的存储,并保持直到程序终止3 。 由于它们是在main
执行之前加载的,因此无法使用表达式初始化它们,直到main
执行之后才能知道其值。
1.我知道至少有一个版本的gcc会构建可执行文件,这样任何static const
-qualified变量都会在加载程序时设置它们的初始值。 然而,他们仍然被视为在main
开始之后才初始化。
2. C ++在这方面有所不同; static const
-qualified变量被认为是该语言的编译时常量。
3.使用static
关键字在函数或块中声明的变量也具有静态存储持续时间,这意味着它们在程序的生命周期中存在,但在该函数或块之外是不可访问的。