Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中的常量和指针_C_Pointers_Constants - Fatal编程技术网

C语言中的常量和指针

C语言中的常量和指针,c,pointers,constants,C,Pointers,Constants,将const与指针一起使用会使指针对象不可修改,方法是使用所讨论的指针取消对它的引用。但是为什么我也不能修改指针没有直接指向的内容呢 例如: int a = 3; const int* ptr = &a; *ptr = 5; 不会编译。但是为什么呢 *(ptr + 2) = 5; 也不编译?我不会更改指针指向的对象。那么,我们是否必须说,以这种方式将const与指针一起使用,不仅使指针指向的对象(通过取消引用指针)不可修改,而且还可以修改使用指针得到的地址所指向的任何其他对象 我知道

将const与指针一起使用会使指针对象不可修改,方法是使用所讨论的指针取消对它的引用。但是为什么我也不能修改指针没有直接指向的内容呢

例如:

int a = 3;
const int* ptr = &a;
*ptr = 5;
不会编译。但是为什么呢

*(ptr + 2) = 5;
也不编译?我不会更改指针指向的对象。
那么,我们是否必须说,以这种方式将const与指针一起使用,不仅使指针指向的对象(通过取消引用指针)不可修改,而且还可以修改使用指针得到的地址所指向的任何其他对象


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

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

如果你写信

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

(奥托,如果你写的话

int * const ptr = &a;
无法修改
ptr

在您的情况下,禁止向目的地写入任何内容


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

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

ptr+2
的类型与
ptr
的类型相同,即是指向
const
对象的指针


指针算法假定指向的对象是一个基类型完全相同的数组。此类型包括
常量
限定。

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

const int* ptr = &a;
ptr
的类型是
const int*

因此,
*ptr
的类型是
const int
。不可修改


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

尽管其他答案解释了它为什么不起作用的技术细节,但我想提供一个更一般的理由:这是唯一有意义的事情

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

*(p + very complex expression) = ...
您的编译器是否应该能够确定
非常复杂的表达式
是否为零?那怎么办

int s;
scanf("%d", &s);
*(p + s) = ...
在这种情况下,编译器应该做什么


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

(请注意
const int*
int const*
是同一件事-指向const的指针,而不是const指针。)还请注意,给定“
int*const ptr=&a;
”,您可以编写“
*ptr=5;
”但不能“
++ptr
”。答案中有很好的规则覆盖——答案的第一行——“向后读”——总结得很好。@frasnian这基本上就是我所说的——
++ptr
包含在“你不能修改
ptr
”中。那么你希望编译器假设只有第一个
sizeof(int)吗
字节是
const
?编译器会假设使用
ptr
访问的任何内存地址都是只读地址(“物理”只读,或者至少在使用
ptr
的函数的“透视图”中是只读的)。好吧,argv只是一个指针,因为写入char*argv[]相当于char**argv。我们只是创建了一个数组的假象。@Root149数组与否在访问它时没有区别,因为访问是通过指针进行的。@Root149:对。由于这种假象,编译器不知道指针是否也是这样的“假象”。它可以用作数组,如
argv
,因此,对它的每次写入访问都必须受到限制(无论是
ptr[0]
还是
ptr[100]
)。所以它就像int+float=float一样,所以const[type]*+某个值=const[type]*,对吗?@Root149,类似的东西,是的。向指针类型添加任何整数类型都会返回相同的指针类型。只有指针类型会衰减(当涉及指针时,所有内容都会变平为指针,包括数组),其中普通整数类型升级为可以表示所有内容的类型。这种行为不是由编译器决策中的任何歧义引起的。它是类型系统规则的简单而正确的结果。@JamesT.Huggett:我不确定你所说的“编译器决策中的歧义”是什么意思"; 确实,这种行为是一个类型规则的结果,我的回答只是试图解释为什么类型系统的规则是这样设计的。