这是常见的“分配时丢弃的const限定词”错误的来源。但是,我不明白为什么这样做是非法的?
考虑此代码,
int sum_array(const int *a, int n){
int sum, *i;
sum = 0;
for(i = a; i<a+n; i++)
sum += *i;
return sum;
}
很明显,我可以使用i = 0
并比较a + i < a+n
来执行相同的操作;但是,对我而言,为什么简单地将一个变量的地址复制到另一个变量中是非法的?
通常,const变量指示变量的值不能更改。例如。 const int x = 7,这里我们声明x的值不应从7更改。
但是,使用const指针创建“电位”来更改变量也是非法的。即i = a不会改变指向的值,真正的“非法”值是* i = 0,但是,i = a仍然是非法的,因为它使我们有可能改变a。
我知道您可以通过“因为语言是通过这种方式创建的”来回答我,我只是想知道这里是否缺少任何内容。
答案 0 :(得分:2)
const
的主要目的是争取编译器的帮助,以确保您不会意外修改给定的对象。为此使用类型系统。您实际上可以通过编写显式强制转换来规避它。但通常您不想要那个,因为如果您想要那个,那通常意味着您并不真正希望const
开始。
答案 1 :(得分:2)
const
有两个用途:
在函数调用协定中(此处为int sum_array(const int *a, int n)
),这意味着函数将不使用参数a
来修改a
所指向的内容( a
不是常数,它是指向被认为是常数的事物的指针。然后,调用者知道不会通过调用修改数据,并且编译器必须尽可能执行以下操作:
在函数定义中,然后保护实现器,防止意外修改a
所指向的内容。即。如果他尝试编写类似*a = someValue;
的内容,则编译器将因违反合同而提出投诉。但是,这也验证了该合同是否得到了尊重。因此,来自a
的任何派生变量可能会提供对相同数据的访问权限,必须将其视为const
,否则将违反合同。然后写入int *p = a
显然是违反此规定的,因为p
不是指向const数据的指针,这将使您可以写入*p = someValue
来修改数据。
请注意:const
并不意味着数据是const,而只是通过指针禁止修改数据。然后:
const int *a...
int *p = a;
被禁止,但是
int *a...
const int *p = a;
是正确的,因为在这种情况下,您有一个指针,可以通过它修改数据,并构造一个派生的指针,该指针限制通过派生的指针访问同一数据。数据可以通过a
修改,但不能通过p
修改。限制从来没有危险,开放可以。
当然,您可以通过强制转换(强制删除const
)来强制执行危险的派生操作,但我不建议这样做。 建议,如果您想这样做,请避免自己动手,再想一想,如果此后您确实想这样做,那就让它挂一整夜,然后第二天再考虑一下。 ..食谱是:
const *a...;
int *p = (int *)a; // "seriously refrain" advice
答案 2 :(得分:1)
该问题提出,给定const int *a
,可以允许int *i = a;
,而不允许随后的*i = 0;
(“非法”)。
这是不可行的,因为它要求编译器跟踪i
中有关数据源的信息。在出现*i = 0;
的那一点上,编译器必须知道i
包含一个从a
初始化而来的值。
我们可以用非常简单的代码来做到这一点。但是考虑到代码可能非常复杂,带有循环,分支和函数调用。在*i = 0;
出现的地方,编译器通常无法知道i
是否仍然保存着a
的地址或已更改为其他地址。 (我希望这等同于暂停问题,因此从逻辑上讲是不可能的)。
C使用类型来管理它。如果a
是指向const
的指针,则只能将其分配给指向const
的指针(除非被显式强制转换覆盖)。因此,i
必须是指向const
的指针,这样编译器才能知道它指向的内容不应该被修改。