c语言 - "const int *ptr=&i"到底是什么意思?为什么它接受非常量地址?



您的回答是为了澄清我今天意识到的对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指向的ptrptr,它说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。

最新更新