const 变量的存储分配

发布于 2024-12-27 06:25:32 字数 407 浏览 3 评论 0原文

我正在读一本书,其中提到了这一点

如果编译器知道 const 的每次使用,则不需要分配 容纳它的空间。例如:

  1. const int c1=1;
  2. const int c3=my_f(3);
  3. extern const int c4;

鉴于 c3 和 c4 的值不知道编译时、存储时 必须分配给c3和c4。

我对此一无所知。我的疑问是:

留在这里是什么意思?不是还需要把所有东西都存到内存里吗? 对于c1,我们不会有任何存储分配吗?

请解答我的疑惑。

谢谢。

I am reading a book which mentions this

If the compiler knows every use of the const, it need not allocate
space to hold it. For example:

  1. const int c1=1;
  2. const int c3=my_f(3);
  3. extern const int c4;

Given that values of c3 and c4 are not known as compile time, storage
must be allocated for c3 and c4.

I didn't understand any of this. My doubts are:

What does it mean by holding here? Wouldn't it still need to store everything in memory?
For c1, wont we have any storage allocation?

Please clear my doubts.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

俯瞰星空 2025-01-03 06:25:33

c1 与其他两个常量的不同之处在于它是用文字值初始化的。这使得编译器可以在使用常量的任何地方放置该值,如下所示:

int x = z + c1;

可以替换为

int x = z + 1;

这意味着编译器不需要分配空间并在其中存储 1

c3c4 是不同的:一个是使用函数计算的,另一个是由不同的编译单元提供的。这意味着编译器无法再像使用 c1 那样执行替换:c3c4 的值未知编译器。因此,编译器生成代码的

int x = z + c4;

方式与 c4 是存储在内存中某个位置的变量相同。由于在这种情况下c4是一个外部常量,链接器将解析它的位置,并填写编译器缺少的信息(即c4的地址)以使得程序完成并准备运行。

c1 is different from the other two constants in that it is initialized with a literal value. This lets compiler put that value everywhere the constant is used, like this:

int x = z + c1;

can be replaced by

int x = z + 1;

This means that the compiler does not need to allocate space and store 1 in it.

c3 and c4 are different: one is calculated using a function, and the other one is supplied from a different compilation unit. This means that the compiler can no longer perform the substitution the way it could with c1: the values of the c3 and c4 are not known to the compiler. Therefore the compiler generates code for

int x = z + c4;

in the same way as if c4 were a variable stored in some place in memory. Since in this case c4 is an external constant, the linker will resolve its location, and fill in the information the compiler is missing (namely, the address of c4) to make the program complete and ready to run.

不即不离 2025-01-03 06:25:33

Const 有 2 个用途 - 替换宏(常量表达式)以及不可变数据。

这个语句:

const int c1=1;

本质上是这个的类型安全版本:

#define c1 1

这样这个代码:

int foo = c1;

可以简单地编译为:

int foo = 1;

哪个更有效。

另一方面,这个:

const int c3=my_f(3);

被用作不可变的 c3。它可能存在于内存中,但您无法修改它。它本质上是 int c3=my_f(3); 的更安全版本。

为了说明这一点:

int a1[c1];
int a2[c3];

a1 是有效的,因为编译器可以将 a1 推断为常量表达式。 a2 不是,因为虽然 c3 是 const,但在编译时可能不知道。

C++11 添加了 constexpr 关键字,该关键字与 const 类似,但比 const 更严格。只有 c1c2 可以是 constexprc3 也可以,尽管它要求 my_f 也是如此。

Const has 2 uses - replacement for macros (constant expressions) and also immutable data.

This statement:

const int c1=1;

Is essentially a type-safe version of this:

#define c1 1

Such that this code:

int foo = c1;

Could simply be compiled as:

int foo = 1;

Which is more efficient.

On the other hand, this:

const int c3=my_f(3);

Is being used as an immutable c3. It likely exists in memory, but you can't modify it. It essentially is a safer version of int c3=my_f(3);.

To illustrate this:

int a1[c1];
int a2[c3];

a1 is valid, as the compiler can deduce a1 to be a constant expression. a2 is not, as while c3 is const, it may not be known at compile-time.

C++11 adds the constexpr keyword which is similar to const, although is more strict than const. Only c1 and c2 could be constexpr. c3 could also be, although it would require that my_f is too.

Hello爱情风 2025-01-03 06:25:33

作为积分常量表达式,编译器完全有权使用常量折叠将其从程序中删除。只有当你知道它的地址时,这才是不正确的。此外,如果可能的话,现代优化编译器可以使用 LTO、内联和常量折叠来对 c3 和 c4 执行相同的操作。

如果您不获取变量的地址,并且编译器可以根据 as-if 规则生成具有等效结果的代码,则没有义务分配它。

编辑:常量折叠是编译器在编译时而不是运行时计算表达式的地方。例如,您可以合法地执行 int x[3 + 4];,其中 3 + 4 在编译时求值。一些示例,特别是涉及 ICE 的示例,是标准强制执行的,但如果可能的话,实施可以执行更多操作。 LTO 是链接时间优化,这是编译器在链接在一起时跨翻译单元执行优化的地方。

这意味着编译器可以内联my_f的主体,然后(取决于主体)constant折叠它,使c3成为一个常量表达式,然后constant折叠它到使用它的地方而不是分配它。对于c4,LTO 可能会产生c4 的值作为常量表达式,在这种情况下,它也可以被常量折叠和删除。

在 C++11 中,有 constexpr 函数允许在此区域执行更多操作。

As an Integral Constant Expression, the compiler has every right to use constant folding to remove it from the program. This is only not true if you take it's address. In addition, a modern optimizing compiler can employ LTO, inlining and constant folding to do the same with c3 and c4, if it's possible.

If you do not take the address of a variable, the compiler has no obligation to allocate it if it can generate code with equivalent outcomes, under the as-if rule.

Edit: Constant folding is where the compiler evaluates expressions at compile-time instead of run-time. For example, you can legally do int x[3 + 4]; where 3 + 4 is evaluated at compile-time. Some examples, specifically those involving ICEs, are Standard mandated, but the implementation can perform more if possible. LTO is Link Time Optimization, which is where the compiler performs optimizations across translation units when they are linked together.

This means that the compiler can inline the body of my_f, and then (depending on the body) constant fold it out to make c3 a constant expression, and then constant fold it into wherever it's used and not allocate it. For c4, LTO might yield the value of c4 as a constant expression, in which case it can be constant folded and removed as well.

In C++11 there are constexpr functions which allow much more to be done in this region.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文