【问题标题】:when the const is considered really a const?当 const 被认为是真正的 const 时?
【发布时间】:2015-02-18 21:10:43
【问题描述】:

在阅读 stackoverflow 中的一些问题和答案时,我遇到了这个question

我试图理解它,但答案真的很难理解,尤其是像

这样的术语
  • 静态存储时长

  • 无法在翻译阶段评估表达式

等等……

此外,我认为常数总是常数(这是我从学校学到的)

请有人能说得通俗一点吗?

【问题讨论】:

  • @KarolyHorvath:C++ 参考不是 C 问题答案的来源...
  • @R.. 实际上 cppreference 也有非常好的 C 文档,虽然不是在所有情况下。
  • @R..:理解一个概念就足够了。
  • objectvalue 是有区别的。对象是基本的东西,但价值观是你看待对象的方式。一个对象可能是也可能不是真正不可变的,但您始终可以通过const访问一个对象。
  • const,尽管这个词有拼写,但并不意味着 constant。这意味着只读

标签: c compiler-errors constants


【解决方案1】:

这里有两个几乎完全不相关的概念:

  • “常量表达式”是可以在编译时运行的代码。
    • 4+5 是一个常量表达式。
    • const A=4; 使A 成为一个常量表达式有时在某些情况下,因为它是const 并从常量表达式4 初始化。 (这只适用于 C++,不适用于 C)
    • B=A; A 本身可能是一个常量表达式,但B 是一个变量,并且本身可能不在常量表达式中。
  • const 变量是函数(或结构)承诺不会改变的变量,尽管其他事物可能会改变同一个变量。

【讨论】:

  • 编译时间是什么意思?
  • @tanit:对 1.3 的观察很好。编译时间是您将代码提供给编译器并生成目标文件的时间,就在链接器将目标文件链接到可执行文件的链接时间之前。
  • 您是指编译(编译器和汇编器阶段)还是仅编译器阶段?请更具体一点?
  • @tanit:在这种情况下,“编译时间”涵盖了从解析到代码生成的所有内容(我假设你的意思是“汇编阶段”)。
【解决方案2】:

在 C 中(与 C++ 不同),算术表达式只有当表达式中的每个值都是数字常量或枚举值的名称时才是“常量表达式”。也就是说,尽管您可能已将变量声明为 static const int,但您仍然不能在常量算术表达式中使用该(常量)变量。

请注意,“常量表达式”是由定义 C 语言的正式标准定义的短语。还有其他的表达式在直觉上是恒定的,但它们不包含在正式定义中。

具有“静态存储持续时间”的变量只是一个存在于整个程序执行过程中的变量。大多数此类变量是全局变量(即不是任何函数的一部分,甚至不是 main),但在 C 和 C++ 中,您可以在函数范围内拥有一个 static 变量。这样的变量只初始化一次,无论函数被调用多少次,都只存在一个实例。

全局变量和其他具有静态存储持续时间的变量,只能按照上述定义初始化为常量表达式。 无论是否都是const 变量。问题只是变量具有静态存储持续时间,这意味着它们必须在程序执行之前进行初始化。 (具有静态存储持续时间的变量存在于整个程序的执行过程中,所以如果它被初始化——也就是说,给定一个初始值,而不是在程序执行期间被分配一个值——初始化必须在程序执行之前发生。)

在 C++ 中,声明为 static const 的变量被视为常量值,因此它可以出现在常量表达式中。然而,在 C 中,情况并非如此,因此 C 编译器不需要跟踪 static const 变量的初始值。

【讨论】:

  • 以前从未遇到过常量表达式这个词! :(
  • @user12448:这是 C 标准第 6.6 节的标题,所以您只需查看目录 :)
  • 请问在哪里可以找到文件? :)
  • @user12448:最新的可用草稿是open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
  • static int var=name_of_variable 一个常量表达式,如果不是为什么?
【解决方案3】:

你被constconstant弄糊涂了。

const 装饰器装饰一个变量,它必须有一个内存位置。(但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是否是实现定义的,因为它真的取决于称为常量替换的优化技巧。

【讨论】:

    【解决方案4】:

    在 C 中,const 限定变量与 常量 不同。整数文字50100 是常量表达式;它们的值在编译时是已知的(也就是说,它们可以在翻译阶段进行评估,这意味着当编译器将源代码翻译成机器代码时)。但是,变量 acd 直到运行时才会设置它们的值1;这意味着它们不能在需要编译时常量的上下文中使用2(它们不能在翻译阶段进行评估)。 const 限定符所做的只是告诉编译器拒绝任何在初始化后尝试修改这些变量的代码。

    链接问题中的问题是 endXendY 是在文件范围内声明的,在任何函数之外。因此,变量具有静态存储持续时间,这意味着当程序第一次加载到内存中时,main 执行之前为它们预留存储空间,并一直保留到程序终止3。由于它们是在 main 执行之前加载的,因此它们无法使用表达式进行初始化,该表达式的值在 after main 执行之前是未知的。


    1。我知道至少有一个版本的 gcc 会构建可执行文件,这样任何static const-qualified 变量都会在程序加载时设置它们的初始值;但是,它们仍然被视为直到main 开始之后才被初始化。

    2、C++在这方面有所不同; static const-qualified 变量认为是该语言中的编译时常量。

    3. 在函数或块中使用 static 关键字声明的变量也具有静态存储期限,这意味着它们在程序的生命周期内都存在,但在该函数或块之外无法访问。

    【讨论】:

      猜你喜欢
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-21
      相关资源
      最近更新 更多