如标题中所述,如果type-qualifiers
影响声明者的存储位置(stack
,bss
等),我会感到困惑。为了描述更多,我正在考虑以下声明。
int main()
{
const int value=5;
const char *str= "Constant String";
}
storage-class-specifier
为auto
。 stack-frame
main
中分配。 pointers
可以自由修改其中包含的值。type-qualifier
要么添加一些逻辑来保存所存储元素的constant
性质(如果是这样的话是什么?)或constants
存储在read-only-portion
内存中。请详细说明。#include <stdio.h>
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);
}
在上面的示例中,cptr
和ptr
都指向同一位置。但cptr
是指向const type qualified
整数的指针。在修改cptr
的值时,编译器会抛出错误,因为“只读位置的分配'* cptr'”。但我可以使用ptr
修改相同位置,如下面的输出所示。请解释
ptr: BFF912D8
cptr: BFF912D8
Value: 10
答案 0 :(得分:0)
在您的第一个示例中:
int main()
{
const int value=5;
const char *str= "Constant String";
}
将存储变量value
和字符串文字的位置留给实现。所有C标准保证的是,这些将存储在只读存储器中,可以在文本段,堆栈或任何地方。
在您的第二个案例中:
int *ptr=&val;
const int *cptr=ptr;
当您尝试修改*cptr
时,编译器不关心cptr
指向的实际位置是只读还是可写。所有它关心的是它认为const
指向的位置的类型限定符cptr
是只读的。
另一种变体:
const int i = 5;
p = &i;
*p = 99;
在这种情况下,编译器允许通过指针修改const值。但这是未定义的行为。
答案 1 :(得分:0)
我不会详细介绍你的例子,但是想做一些一般性的评论:
C语言语义仅在一定程度上由编译器和硬件强制执行:程序员有责任避免未定义的行为。
例如,通过从指针中删除constness而不会出现段错误(硬件强制执行)或编译器错误(转换器告诉它),很可能修改自动存储持续时间(堆栈分配)的const限定变量因为你知道你在做什么而闭嘴。
然而,语言限制将被违反,并且代码将在实践中中断,因为优化器将做出不再适用的假设。
然后,有一种误解,即用于访问对象的表达式的类型与操作的定义相关 - 它不是。
有效的输入规则(C996.5§6)实质上使C成为一种非常不健全的类型系统的强类型语言。类型信息(其中包含可变性)由对象(存储位置)本身承载,而不管位置如何被访问。
这使得存储到const限定的存储位置非法(未定义的行为)但技术上可行(不健全的类型系统)。通过指针进行任意类型的惩罚属于违反语言语义的相同类别的操作,但是没有强制执行,因此可能导致奇怪的错误,例如在严格别名的假设下。