类型限定符对存储位置的影响

正如标题中所提到的,如果type-qualifiers影响声明bss的存储位置( stackbss等),我很困惑。为了描述更多,我正在考虑以下声明。

 int main() { const int value=5; const char *str= "Constant String"; } 
  • 在上面的代码中,默认的storage-class-specifierauto
  • 因此,假设这些常量将在创建时在mainstack-frame中分配。
  • 通常, pointers堆栈中各种存储器位置的pointers可以自由地修改其中包含的值。
  • 因此,从以上几点可以理解, type-qualifier添加了一些逻辑来保存所存储元素的constant性质(如果是这样的话是什么?)或者constants存储在存储器的read-only-portion中。 请详细说明

更详细的例子

 #include  int main(void) { int val=5; int *ptr=&val; const int *cptr=ptr; *ptr=10; //Allowed //*cptr=10; Not allowed //Both ptr and cptr are pointing to same locations. But why the following error? //"assignment of read-only location '*cptr'" printf("ptr: %08X\n",ptr); printf("cptr: %08X\n",cptr); printf("Value: %d\n",*ptr); } 

在上面的例子中, cptrptr指向同一个位置。 但是cptr是指向const type qualified整数的指针。 在修改cptr的值时,编译器cptr错误抛出为“只读位置’* cptr’的分配” 。 但我可以用ptr修改相同的位置 ,如下面的输出。 请解释

 ptr: BFF912D8 cptr: BFF912D8 Value: 10 

在你的第一个例子中:

 int main() { const int value=5; const char *str= "Constant String"; } 

将存储变量value和字符串文字的地方留给实现。 所有C标准保证的是,这些将存储在只读存储器中,可以在文本段,堆栈或任何地方。

在你的第二种情况:

  int *ptr=&val; const int *cptr=ptr; 

当您尝试修改*cptr ,编译器不关心cptr指向的实际位置是只读还是可写。 所有它关心的是它认为cptr指向的位置的类型限定符const是只读的。

另一个变种:

  const int i = 5; p = &i; *p = 99; 

在这种情况下,编译器允许通过指针修改const值。 但这是未定义的行为

我不会详细介绍你的例子,但是想做一些一般性的评论:

C语言语义仅在一定程度上由编译器和硬件强制执行:程序员有责任避免未定义的行为。

举个例子,很可能通过从指针中删除constness来修改自动存储持续时间(堆栈分配)的const限定变量,而不会出现段错误(硬件强制执行)或编译器错误(演员表示它会关闭因为你知道你在做什么。

然而,语言限制将被违反,并且代码将在实践中中断,因为优化器将做出不再成立的假设。

然后,有一种误解,即用于访问对象的表达式的类型与操作的定义相关 – 事实并非如此。

有效的输入规则(C996.5§6)实质上使C成为一种非常不健全的类型系统的强类型语言。 类型信息(其中可变性)由对象(存储位置)本身承载,而不管如何访问位置。

这使得存储到const限定的存储位置是非法的(未定义的行为),但技术上可行(不健全的类型系统)。 通过指针的任意类型惩罚属于违反语言语义的相同类别的操作,但是没有强制执行,因此可能导致奇怪的错误,例如在严格别名的假设下。