C语言中限定词的深层分析

jac*_*ack 8 c const

const变量在哪里准确存储,它的行为如何变化?比如说:

const int i=10; // stores where ?  
main()  
{  
   const int j=20; //stores where?   
   return 0;  
}  
Run Code Online (Sandbox Code Playgroud)

如果答案是代码段,那么以下代码如何工作?

main()  
{  
   const int j=20;  
   int *p;  
   p=&j;  
   (*p)++;   
   return 0 ;  
} 
Run Code Online (Sandbox Code Playgroud)

这段代码工作正常......如何更改只读内存?它是如何真正存储的?请详细解释一下.

Cod*_*ray 9

关键字const表示只读变量(即,无法在运行时更改).它不表示编译时常量.因此,变量的所有通常属性都适用; 具体而言,它被分配了可寻址的存储空间.

与之不同#define,您的常量不一定由编译器内联.相反,编译器将const在目标文件中创建与您的声明相对应的符号,以便可以从其他代码文件访问它 - 请记住,const对象在C中默认具有外部链接(尽管某些编译器仍会内联文件中的常量值)在哪里定义).

您发布的"工作"代码片段的原因是因为一元运算符&可以应用于包含const对象的任何左值.虽然这里的行为是未定义的,但我怀疑你的编译器正在检测这种用法,并确保你的const声明被赋予地址空间,因此不会内联它,即使在声明它的文件中也是如此.

编辑:另见:http://publications.gbdirect.co.uk/c_book/chapter8/const_and_volatile.html

让我们来看看使用const时的含义.它非常简单:const意味着某些东西不可修改,因此在程序运行期间不得以任何方式将以const作为其类型规范的一部分声明的数据对象分配.对象的定义很可能包含一个初始值设定项(否则,因为你不能赋值给它,它将如何得到一个值?),但情况并非总是如此.例如,如果您访问固定内存地址的硬件端口并承诺只读取它,那么它将被声明为const但未初始化.

获取非const类型的数据对象的地址并将其放入指向相同类型的const限定版本的指针中是安全且明确允许的; 您将能够使用指针检查对象,但不能修改它.将const类型的地址放入指向非限定类型的指针更加危险并因此被禁止(尽管您可以通过使用强制转换来解决这个问题).例如...

  • 这是一个很好的答案.当我遇到一个声明为`const volatile`的变量(它是一个硬件寄存器)时,我只完全理解了`const`在C中的含义.在我最初的WTF时刻之后,我意识到`const`只意味着******,程序员,保证不会改变它.如果你希望通过其他方式改变它,你需要`volatile`.但是编译器并没有把它解释为编译时常量(就像在`C++中,我认为). (4认同)

caf*_*caf 7

修改您的代码以打印值:

#include <stdio.h>

main()
{
   const int j=20;
   int *p;
   p=&j;
   (*p)++;
    printf("%d\n", j);
   return 0 ;
}
Run Code Online (Sandbox Code Playgroud)

上面的代码在使用 gcc 4.3.2-O1优化或更高版本编译时,会产生输出20而不是21. 这表明它并没有真正“起作用”——它只是看起来起作用了。

一个const限定词是不是有放置在特定种类的内存变量的请求-这是从你的编译器一个承诺,你不会以任何方式修改该变量。编译器可以依靠你的承诺来优化生成的代码——如果你违背了你的承诺,它不一定会以明显的方式破坏,它可能只会产生奇怪的结果。