C中的const和指针

使用带指针的const可以通过使用有问题的指针解除引用,使得指针对象无法修改。 但为什么我也不能修改指针没有直接指向的东西?

例如:

int a = 3; const int* ptr = &a; *ptr = 5; 

不会编译。 但为什么呢

 *(ptr + 2) = 5; 

还没编译? 我没有改变指针指向的内容。
所以我们不得不说使用带有指针的const这样不仅使得指针指向的东西不可修改(通过解引用指针)而且还有其他任何东西,我们使用指针得到的地址是什么?

我知道在示例中我试图访问未分配的内存,但这只是为了讨论。

ptr +2ptr具有相同的类型, ptrconst对象的指针。

指针算术假设指向的对象是所有相同基类型的数组。 此类型包括const限定。

const引入的不可修改性取决于const的写入位置。

如果你写

 const int * ptr = &a; 

(或int const * ptr = &a; ), const引用指针对象,因此禁止使用指针写入目标。

(OTOH,如果你写的话

 int * const ptr = &a; 

你无法修改ptr 。)

在您的情况下,禁止写入目的地的所有内容。

这包括*ptrptr[0] (它们是等价的),但也包括修改目标地址的所有内容,例如*(ptr + 2)ptr[2]

虽然其他答案解释了为什么它不起作用的技术性,但我想提供一个更普遍的理由:它是唯一有意义的东西。

问题是编译器没有通用的方法来决定p + something是否与p + something相同,因为something可能是任意复杂的。 像“ pp + 0指向的值是不可修改的,但仍然可以修改其他值”的规则在编译时无法检查:想象一下如果你写了:

 *(p + very complex expression) = ... 

您的编译器是否应该能够确定very complex expression是否为零? 关于什么

 int s; scanf("%d", &s); *(p + s) = ... 

在这种情况下编译器应该做什么?

这里唯一合理的选择是通过p不可修改来访问任何值。

由于指针也可以用作数组(想想argv ),编译器会限制涉及指针的每个访问。 这样整个数组就是只读的。

让我们考虑一下表达式的类型。

 const int* ptr = &a; 

ptr的类型是const int*

所以*ptr的类型是const int 。 不可修改。

(ptr + 2)的类型仍然是const int*所以*(ptr + 2)的类型是const int ,这也是不可修改的。