编译器,C或C ++(例如gcc)如何表彰const
声明?
例如,在以下代码中,编译器如何跟踪变量ci
是const
并且无法修改?
int
get_foo() {
return 42;
}
void
test()
{
int i = get_foo();
i += 5;
const int ci = get_foo();
// ci += 7; // compile error: assignment of read-only variable ?ci?
}
答案 0 :(得分:10)
与变量的任何其他位符号信息(地址,类型等)非常相似。通常有一个符号表存储有关已声明标识符的信息,每当遇到另一个对标识符的引用时,都会查询它。
(一个更有趣的问题是这些知识是仅在编译期间还是在运行期间出现。大多数语言在编译后丢弃符号表,因此即使标识符被声明,您也可以操纵编译的代码并强制使用新值const'。它需要一个复杂的运行时系统(和代码签名)来防止这种情况发生。)
答案 1 :(得分:3)
当然,这是每个编译器的实现,但简而言之,它将变量的const
和volatile
限定符(如果有)存储在其变量符号表中以及其他信息,如变量的类型以及它是否是指针/引用。
答案 2 :(得分:1)
编译器知道ci
是const
,因为你用行告诉了它
const int ci = get_foo();
当您将ci
传递给其他函数或将其分配给其他变量时,编译器会通过阻止您执行可能会更改其值的任何操作来保留该常量。
例如,以下内容会产生编译器错误。
int *ci2 = &ci;
(*ci2)++;
因为编译器不允许你修改ci的值。
答案 3 :(得分:1)
我相信其他人可以详细说明,但简而言之,是的。编译器跟踪所有类型说明符,以便它知道ci的类型为“const int”,而不是“int”。
答案 4 :(得分:1)
正如其他人所说,编译器跟踪const
的方式与编译器跟踪变量为int
这一事实的方式相同。事实上,我已经读过,至少gcc认为const int
是int
的一个不同的类型,因此它甚至不被跟踪为修饰符,它的跟踪方式与int
完全相同。
请注意,您实际上可以通过指针转换来更改const
的值,但结果是未定义的:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
const int c = 0;
printf("%d\n", c);
++*(int*)&c;
printf("%d\n", c);
}
在我的机器上使用gcc打印
0
1
但是用g ++编译会给出
0
0