【问题标题】:Why are those definitions not legal in C?为什么这些定义在 C 中不合法?
【发布时间】:2020-08-06 09:21:02
【问题描述】:

我正在读一本关于 C 的书,但我不明白这个概念:

另一个常见的误解是将 const 限定变量视为常量表达式。在 C 中, const 表示“只读”,而不是“编译时间常数”。所以,像 const int SIZE = 10; 这样的全局定义int global_arr[大小];和 const int SIZE = 10; int global_var = 大小;在 C 中是不合法的。

我也不太了解 const 变量和常量表达式之间的区别。所有 const 变量都是常量表达式,对吧?我已经阅读了有关此主题的其他问题,但我仍然不了解。谢谢。

【问题讨论】:

标签: c constants global variable-assignment variable-length-array


【解决方案1】:

假设你有

int a = 42;
const int *b = &a;

现在*bconst只读。你不能改变*b而不把const扔掉(感谢Eric Postpischil)

// *b = -1; // not allowed
a = -1;
printf("%d\n", *b); // print -1

重点是:const 限定对象的值可能改变。一个常数值从不改变。

【讨论】:

  • 我不认为那是那个段落所指的。我认为这只是在谈论“const 限定变量”如何不能用于 c 期望常量“表达式”的地方,例如一个“文字”。
  • 你也可以拥有const volatile对象!!
  • Re “You are not allowed to change *b”:int a = 42; const int *b = &a; 之后,* (char *) b = 73; 的行为由 C 标准定义,* (char *) &*b = 73; 的行为也是如此。
【解决方案2】:

它们的基本意思是,在 C 中,使用 const 限定变量来初始化另一个变量或在全局范围内用它确定数组的大小是非法的,例如:

const int SIZE = 5;
int a = SIZE;              // This is not allowed.
int b[SIZE];               // This is also not allowed.

int main(void)
{
   ...
}

这是因为全局范围内的变量和数组需要在编译时确定const 限定变量仍然是一个变量,变量的值在运行时计算/评估。

一个宏常量,它是一个“编译时间常量”,可以用于此,如 f.e.:

#define SIZE 15

int a[SIZE];             // This is ok.
int b = SIZE;            // This is ok, too.

我也不太明白const变量和常量表达式的区别。所有const 变量都是常量表达式,对吧?

没有。

引自 ISO:IEC 9899/2018 (C18),第 6.6/2 节:

"常量表达式可以在翻译过程中而不是运行时求值,因此可以在常量可能存在的任何地方使用。"

常量表达式是一个文字表达式,它总是被评估为相同的值 - 评估的值是常量。因此它可以在编译时进行评估。

F.e.:

5 + 4 

始终为 9,因此可以在编译时进行评估。

const 变量:

const int SIZE = 5;

(const int SIZE 5;)

5 + 9 + SIZE; 

不是一个常量表达式,因为它暗示了一个变量。尽管变量SIZEconst 限定(这意味着它在初始化后不能被修改),但它不是一个常量表达式,因为一个变量,不管它是否const,都是计算出来的/在运行时评估。

const 限定变量不是也不能是常量表达式的一部分。

【讨论】:

  • 但如果: const int a = 10;常量a的值不是常量表达式吗?现在我相信我也不能这样做:int variable a = 3; int global_array[a]。但我可以这样做: int global_array[3+2*2];我是对的?
  • @William94 在 C 语言中,不幸的是 const 变量仍被视为变量,而在 C++ 中,您实际上可以使用 const作为数组的大小或初始化全局变量。编辑:是的,您可以使用 3+2*2 之类的东西作为数组的大小
  • @William94 "常量 a 的值不是常量表达式?" 不,因为 a 的值是在运行时计算的。 - 你可以做int variable a = 3; int global_array[a],因为a 不符合const 的条件。例如,您也可以这样做:int gloabl_array[a+2+b];.
  • 即使对于静态对象,使用const 对象作为初始化器也不是非法。它没有被定义为严格符合 C 的一部分,但 C 实现可能支持它。
  • 初始化器是否必须是常量表达式的决定因素是它是否用于具有静态或线程存储持续时间的对象,而不是声明是否出现在全局范围内。请参阅 C 2018 6.7.9 4. C 标准没有所谓的“全局范围”,这是用词不当,因为它意味着在整个程序中可见,而不仅仅是在任何函数外部。因此,它只适用于具有外部链接的标识符,但具有内部链接的静态对象也需要常量表达式
猜你喜欢
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
  • 2019-04-29
  • 1970-01-01
  • 1970-01-01
  • 2017-05-16
  • 1970-01-01
相关资源
最近更新 更多