C语言中的常量和指针
将const与指针一起使用会使指针对象不可修改,方法是使用所讨论的指针取消对它的引用。但是为什么我也不能修改指针没有直接指向的内容呢 例如:C语言中的常量和指针,c,pointers,constants,C,Pointers,Constants,将const与指针一起使用会使指针对象不可修改,方法是使用所讨论的指针取消对它的引用。但是为什么我也不能修改指针没有直接指向的内容呢 例如: int a = 3; const int* ptr = &a; *ptr = 5; 不会编译。但是为什么呢 *(ptr + 2) = 5; 也不编译?我不会更改指针指向的对象。那么,我们是否必须说,以这种方式将const与指针一起使用,不仅使指针指向的对象(通过取消引用指针)不可修改,而且还可以修改使用指针得到的地址所指向的任何其他对象 我知道
int a = 3;
const int* ptr = &a;
*ptr = 5;
不会编译。但是为什么呢
*(ptr + 2) = 5;
也不编译?我不会更改指针指向的对象。那么,我们是否必须说,以这种方式将const与指针一起使用,不仅使指针指向的对象(通过取消引用指针)不可修改,而且还可以修改使用指针得到的地址所指向的任何其他对象
我知道在这个例子中,我试图访问未分配的内存,但这只是为了讨论。const引入的不可修改性取决于
const
的写入位置
如果你写信
const int * ptr = &a;
(或int const*ptr=&a;
),const引用指针对象,因此禁止使用指针写入目标
(奥托,如果你写的话
int * const ptr = &a;
无法修改ptr
)
在您的情况下,禁止向目的地写入任何内容
这包括
*ptr
和ptr[0]
(它们是等效的),但也包括涉及修改目标地址的所有内容,例如*(ptr+2)
或ptr[2]
,因为指针也可以用作数组(想想argv
),编译器限制指针所涉及的每次访问。这样,整个数组是只读的。ptr+2
的类型与ptr
的类型相同,即是指向const
对象的指针
指针算法假定指向的对象是一个基类型完全相同的数组。此类型包括
常量
限定。让我们考虑一下表达式的类型
const int* ptr = &a;
ptr
的类型是const int*
因此,*ptr
的类型是const int
。不可修改
(ptr+2)
的类型仍然是const int*
,因此*(ptr+2)
的类型是const int
,这也是不可修改的。尽管其他答案解释了它为什么不起作用的技术细节,但我想提供一个更一般的理由:这是唯一有意义的事情
问题是编译器没有通用的方法来决定p+something
是否与p
相同,因为something
可以任意复杂。像“由p
和p+0
指向的值是不可修改的,但其他值仍然可以修改”这样的规则在编译时无法检查:想象一下,如果您编写:
*(p + very complex expression) = ...
您的编译器是否应该能够确定非常复杂的表达式
是否为零?那怎么办
int s;
scanf("%d", &s);
*(p + s) = ...
在这种情况下,编译器应该做什么
这里唯一合理的选择是使通过
p
访问的任何值都不可修改。(请注意const int*
和int const*
是同一件事-指向const的指针,而不是const指针。)还请注意,给定“int*const ptr=&a;
”,您可以编写“*ptr=5;
”但不能“++ptr
”。答案中有很好的规则覆盖——答案的第一行——“向后读”——总结得很好。@frasnian这基本上就是我所说的——++ptr
包含在“你不能修改ptr
”中。那么你希望编译器假设只有第一个sizeof(int)吗
字节是const
?编译器会假设使用ptr
访问的任何内存地址都是只读地址(“物理”只读,或者至少在使用ptr
的函数的“透视图”中是只读的)。好吧,argv只是一个指针,因为写入char*argv[]相当于char**argv。我们只是创建了一个数组的假象。@Root149数组与否在访问它时没有区别,因为访问是通过指针进行的。@Root149:对。由于这种假象,编译器不知道指针是否也是这样的“假象”。它可以用作数组,如argv
,因此,对它的每次写入访问都必须受到限制(无论是ptr[0]
还是ptr[100]
)。所以它就像int+float=float一样,所以const[type]*+某个值=const[type]*,对吗?@Root149,类似的东西,是的。向指针类型添加任何整数类型都会返回相同的指针类型。只有指针类型会衰减(当涉及指针时,所有内容都会变平为指针,包括数组),其中普通整数类型升级为可以表示所有内容的类型。这种行为不是由编译器决策中的任何歧义引起的。它是类型系统规则的简单而正确的结果。@JamesT.Huggett:我不确定你所说的“编译器决策中的歧义”是什么意思"; 确实,这种行为是一个类型规则的结果,我的回答只是试图解释为什么类型系统的规则是这样设计的。