“const int * ptr =&i”究竟是什么意思?为什么它接受非常数的地址?
你的答案非常寻求清除我对今天意识到的const
理解中的这个主要缺陷。
在我的程序中,我使用了语句const int *ptr=&i;
但是没有对变量i使用任何const
限定符。两件事令我困惑:
1)当我尝试使用ptr
修改i的值时,我使用了const int *ptr=&i;
,我得到assignment of read-only location '*ptr'|
的错误assignment of read-only location '*ptr'|
,即使我没有用const
限定符声明变量i 。那究竟是什么语句const int *ptr=&i;
是什么意思,它与int * const ptr=&i;
什么不同int * const ptr=&i;
?
我把它钻进了我的脑袋里, const int *ptr=&i;
表示指针存储常量的地址,而int * const ptr=&i;
指的是指针本身是常量并且不能改变。但今天有一个用户在讨论中告诉我( LINK ) const int *ptr means the memory pointed to must be treated as nonmodifiable _through this pointer_
。我发现这个新的东西就像这个意思是“一些选择指针不能改变值(而其他人可以改变)”。我不知道这样的选择性声明!!但是一个180k的老手certificate了那个用户是正确的!!所以你能说出来吗更清晰,更详细,更严谨的方式?“const int * ptr =&i;究竟是什么? 意思?
2)我还被告知我们可以在语句const int *ptr=&i;
对程序撒谎 const int *ptr=&i;
通过为指针指定非常量的地址。这意味着什么?为什么我们允许这样做?如果我们将非常量的地址分配给预期的指针ptr
,为什么不得到警告?一个常量的地址?如果它是如此宽容被分配非常量的地址,为什么当我们试图改变那个非常数的值时会抛出一个错误,这是一个合理的事情,指向的变量是一个非常数?
#include int main () { int i=8; const int *ptr=&i; *ptr=9; printf("%d",*ptr); }
错误: assignment of read-only location '*ptr'|
定义const int *ptr = &i;
本质上说“我不会通过ptr
修改i
。”它没有说ptr
指向的int
是const
,它说ptr
不应该用来修改它。
这种转换是允许的,因为它是有道理的:因为i
不是const
,我可以修改它,但我也可以选择不修改它。 当我选择不修改i
时,没有规则被破坏。 并且,如果我创建一个指向i
的指针并说“我不会使用此指针来修改i
”,那也没关系。
您希望这样做的原因是您可以将对象的地址传递给一个带有指向const
对象的指针的例程。 例如,考虑strlen
例程。 strlen
例程不会修改其输入,因此其参数是指向const char
的指针。 现在,我有一个指向char
的指针,我想知道它的长度。 所以我打电话给strlen
。 现在我传递一个指向char
的指针作为参数的参数,该参数是指向const char
指针。 我们希望转换工作。 它完全有道理:如果我愿意, 我可以修改我的char
,但strlen
例程不会,所以它将它们视为const char
。
1)你得到*ptr = something;
的错误*ptr = something;
因为你将ptr
声明为指向const int
的指针,但是你违反了你不使用ptr
修改int
承诺。 事实上, ptr
指向一个非const
的对象并不否定你不使用ptr
来修改它的承诺。
2)将非const
对象的地址分配给指向const
的指针并不是一个谎言。 赋值并没有说对象是const
,它表示不应该使用指针来修改对象。
此外,虽然您没有问过这个问题,但C中的const
属性并不完全绑定。 如果将对象定义为const
,则不应对其进行修改。 但是,在其他情况下,将指向const
的指针传递给例程,该例程将其转换为指向非const
的指针。 这实际上是语言中的缺陷,无法保留以我们可能更喜欢的方式处理const
所需的所有信息。 一个例子是strchr
例程。 它的声明是char *strchr(const char *s, int c)
。 参数s
是const char *
因为strchr
不会更改其输入。 但是, strchr
例程的指针是从s
派生s
(它指向字符串中的一个字符)。 因此,在内部, strchr
已将const char *
转换为char *
。
这允许您编写将char *
传递给strchr
并使用返回的指针修改字符串的代码,这很好。 但这意味着编译器无法完全保护您免受错误的影响,例如将const char *
传递给strchr
并使用返回的指针尝试修改字符串,这可能是一个错误。 这是C的一个缺点。
解开这个:
const int * ptr表示“* ptr是一个const int”; 即“ptr是指向const int的指针”。 你不能写* ptr = 9,因为* ptr是一个常量。 但是你可以写int j; ptr =&j; 因为你可以允许指针ptr指向不同的int。
int * const ptr表示“ptr是指向int的常量指针”。 您可以编写* ptr = 9,因为您没有更改ptr指向的地址。 你不能把它分配给其他东西; 即int j; ptr =&j; 不会编译。
对于第二部分(2),使用const int * ptr是非常有用的,特别是在函数原型中,因为它告诉函数的调用者ptr指向的变量不会被函数修改。 至于赋值,如果你有int * m =&i,那么ptr = m就可以,但是m = ptr是不行的,因为后者将“抛弃constness”; 即你已经绕过了常规。