4

您的回答非常有助于清除我对const我今天意识到的这一点的理解中的这个主要缺陷。

在我的程序中,我使用了该语句const int *ptr=&i;,但没有对变量iconst使用任何限定符。有两件事让我感到困惑:

1)当我尝试使用我使用的地方修改i的值时,我得到错误,即使我没有用限定符声明变量i 。那么该语句的确切含义是什么以及它有何不同?ptrconst int *ptr=&i;assignment of read-only location '*ptr'|constconst int *ptr=&i;int * const ptr=&i;

我把它钻进了我的脑海,这const int *ptr=&i;意味着指针存储了一个常量的地址,而int * const ptr=&i;意味着指针本身是常量并且不能改变。但是今天一位用户在讨论(链接)中告诉我const int *ptr means the memory pointed to must be treated as nonmodifiable _through this pointer_。我发现这是一些新的东西因为这有点意思是“一些选择指针不能改变值(而其他人可以)”。我不知道这种选择性声明!!但是一个 180k 的老手证明了那个用户是正确的!!你也可以以更清晰、更详细和更严格的方式陈述这一点? `const int *ptr=&i; 到底是什么?意思是?

2)我还被告知,我们可以通过将非常量的地址分配给指针来欺骗语句中的程序。const int *ptr=&i;这是什么意思?为什么允许我们这样做?为什么我们不会得到警告如果我们将非常量的地址分配给期望常量地址的指针ptr?如果它对分配非常量的地址如此宽容,为什么当我们尝试更改非常量的值时会抛出错误- 常数,这是一个合理的做法,指出的变量是一个非常数?

#include <stdio.h>

int main ()
{
 int i=8;
 const int *ptr=&i;
 *ptr=9;
 printf("%d",*ptr);
}

错误: assignment of read-only location '*ptr'|

4

2 回答 2

6

该定义const int *ptr = &i;本质上是说“我不会修改i通过ptr.”。它并没有说指向的那个是int,它说不应该用来修改它。ptrconstptr

允许这种转换是因为它有意义:因为iis not const,所以我可以修改它,但我也可以选择不修改它。当我选择不修改时,没有违反规则i。而且,如果我创建一个指针i并说“我不会使用这个指针来修改i”,那也很好。

您想要这样做的原因是,您可以将对象的地址传递给接受指向const对象的指针的例程。例如,考虑strlen例程。该strlen例程不修改其输入,因此其参数是指向const char. 现在,我有一个指向 的指针char,我想知道它的长度。所以我打电话strlen。现在我将指针char作为参数传递给指向 的参数const char。我们希望这种转换能够奏效。这完全有道理:如果我愿意,可以修改我char的,但strlen例程不会,所以它将它们视为const char.

1)您收到错误,*ptr = something;因为您声明ptr为指向 的指针const int,但随后您违反了不用于ptr修改int. ptr指向不是的对象的事实const不会否定您不使用ptr修改它的承诺。

const2) 将非对象的地址分配给指向 的指针不是谎言const。赋值不是说对象是const,而是说指针不应该用来修改对象。

此外,尽管您没有问过这个问题,但constC 中的属性并不是完全绑定的。如果将对象定义为const,则不应修改它。但是,在其他情况下,将指针const传递给将其转换为指向非指针的例程const。这实际上是语言的缺陷,无法保留以const我们可能喜欢的方式处理所需的所有信息。一个例子是strchr例程。它的声明是char *strchr(const char *s, int c). 该参数sconst char *因为strchr不改变其输入。但是,strchr例程所派生的指针s(它指向字符串中的字符之一)。因此,在内部,strchr已将 a 转换const char *char *.

这允许您编写传递 a 的代码char *strchr使用返回的指针来修改字符串,这很好。但这意味着编译器无法完全保护您免受错误的影响,例如传递 a和使用const char *返回strchr的指针尝试修改字符串,这可能是一个错误。这是 C 语言的一个缺点。

于 2013-05-14T14:00:00.027 回答
-1

解开这个:

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”;即你已经绕过了const。

于 2013-05-14T13:03:45.043 回答