您的回答是为了澄清我今天意识到的对const
的理解中的这一主要缺陷。
在我的程序中,我使用了语句const int *ptr=&i;
,但没有为变量I使用任何const
限定符
1(当我尝试使用ptr
修改I的值时,其中我使用了const int *ptr=&i;
,我得到了错误assignment of read-only location '*ptr'|
,尽管我没有用const
限定符声明变量I。那么语句const int *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_
。我发现这是一个新的东西,因为这有点意味着"一些选择指针不能改变值(而其他指针可以("。我不知道有这样的选择性声明!!但一位18万的资深用户证明了这一点,即该用户是正确的!!。那么,你能以更清晰、更详细、更严格的方式来说明这一点吗?什么是`const int*ptr=&i平均值?
2(我还被告知,我们可以通过将一个非常量的地址分配给指针来对语句ptr
中的程序撒谎。这是什么意思?为什么我们被允许这样做?如果我们将一个非常量的地址分配给指针assignment of read-only location '*ptr'|
(它需要一个常量的地址(,为什么不得到警告?如果它对被指定为非常数的地址如此宽容,为什么当我们试图改变该非常数的值时,它会抛出错误,这是一件合理的事情,因为指向的变量是非常数?
#include <stdio.h>
int main ()
{
int i=8;
const int *ptr=&i;
*ptr=9;
printf("%d",*ptr);
}
错误:const int *ptr = &i;
定义i
本质上说"我不会通过int
修改ptr
。"它没有说const
指向的ptr
是ptr
,它说i
不应该用来修改它。
允许此转换是因为它是有意义的:由于const
不是i
,所以允许我修改它,但我也可以选择不修改它。当我选择不修改i
时,不会违反任何规则。而且,如果我创建一个指向i
的指针,并说"我不会用这个指针来修改const
",那也没关系。
之所以要这样做,是为了将对象的地址传递给一个例程,该例程将指针指向strlen
对象。例如,考虑strlen
例程。const char
例程不修改其输入,因此其参数是指向char
的指针。现在,我有一个指向strlen
的指针,我想知道它的长度。所以我打电话给char
。现在我传递一个指向const char
的指针,作为指向char
的参数的参数。我们希望这种转变能够奏效。这是完全有意义的:如果我愿意,I可以修改我的strlen
,但const char
例程不会修改,所以它将它们视为*ptr = something;
。
1( ptr
出现错误,因为您将const int
声明为指向ptr
的指针,但随后违反了不使用int
修改ptr
的承诺。const
指向一个不是ptr
的对象这一事实并不能否定您不使用const
修改它的承诺
2( 将非const
对象的地址分配给指向const
的指针不是谎言。赋值没有说明对象是const
,而是说明指针不应用于修改对象。
此外,尽管您没有问这个问题,但C中的const
属性并不是完全绑定的。如果您将对象定义为const
,则不应修改它。但是,在其他情况下,指向const
的指针会传递给例程,例程会将其转换为指向非const
的指针。这实际上是语言中的一个缺陷,无法保留以我们可能喜欢的方式处理strchr
所需的所有信息。char *strchr(const char *s, int c)
例程就是一个例子。其声明为s
。参数const char *
是strchr
,因为strchr
不改变其输入。但是,s
例程的指针是从strchr
派生的(它指向字符串中的一个字符(。因此,在内部,const char *
已经将char *
转换为char *
。
这允许您编写代码,将strchr
传递给const char *
,并使用返回的指针修改字符串,这很好。但这意味着编译器无法完全保护您免受错误的影响,例如将strchr
传递给CCD_69,并使用返回的指针尝试修改字符串,这可能是一个错误。这是C.的一个缺点
解开这个:
const-int*ptr表示"*ptr是const int";即"ptr是指向常量int的指针"。你不能写*ptr=9,因为*ptr是一个常数。但是,您可以编写int j;ptr=&j;因为您可以允许指针ptr指向不同的int.
int*constptr表示"ptr是指向int的常量指针"。你可以写*ptr=9,因为你没有改变ptr指向的地址。但是你不能把它分配给其他东西;即int j;ptr=&j;将不会编译。
至于第二部分(2(,const int*ptr非常有用,尤其是在函数原型中,因为它"告诉"函数的调用方ptr所指向的变量不会被函数修改。至于赋值,如果你有int*m=&i、 则ptr=m是可以的,但m=ptr是不可以的,因为后者将"消除constness";即你绕过了const。