[英]Why isn't it legal to convert "pointer to pointer to non-const" to a "pointer to pointer to const"
It is legal to convert a pointer-to-non-const to a pointer-to-const.将指向非常量的指针转换为指向常量的指针是合法的。
Then why isn't it legal to convert a pointer to pointer to non-const to a pointer to pointer to const ?那么为什么将指向非 const的指针的指针转换为指向 const的指针的指针是不合法的呢?
Eg, why is the following code illegal:例如,为什么下面的代码是非法的:
char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char **ps = a; // error!
From the standard:从标准:
const char c = 'c';
char* pc;
const char** pcc = &pc; // not allowed
*pcc = &c;
*pc = 'C'; // would allow to modify a const object
Ignoring your code and answering the principle of your question, see this entry from the comp.lang.c FAQ: Why can't I pass a char ** to a function which expects a const char **?忽略您的代码并回答您的问题的原则,请参阅 comp.lang.c 常见问题解答中的此条目:为什么我不能将 char ** 传递给需要 const char ** 的函数?
The reason that you cannot assign a
char **
value to aconst char **
pointer is somewhat obscure.不能将
char **
值分配给const char **
指针的原因有些模糊。 Given that theconst
qualifier exists at all, the compiler would like to help you keep your promises not to modifyconst
values.鉴于
const
限定符完全存在,编译器希望帮助您遵守不修改const
值的承诺。 That's why you can assign achar *
to aconst char *
, but not the other way around: it's clearly safe to "add"const
-ness to a simple pointer, but it would be dangerous to take it away.这就是为什么您可以将
char *
分配给const char *
,而不是相反:将const
-ness“添加”到一个简单的指针显然是安全的,但将其删除会很危险。 However, suppose you performed the following more complicated series of assignments:但是,假设您执行了以下更复杂的一系列作业:
const char c = 'x'; /* 1 */ char *p1; /* 2 */ const char **p2 = &p1; /* 3 */ *p2 = &c; /* 4 */ *p1 = 'X'; /* 5 */
In line 3, we assign a
char **
to aconst char **
.在第 3 行,我们将
char **
分配给const char **
。 (The compiler should complain.) In line 4, we assign aconst char *
to aconst char *
;(编译器应该抱怨。)在第 4 行,我们将
const char *
分配给const char *
; this is clearly legal.这显然是合法的。 In line 5, we modify what a
char *
points to--this is supposed to be legal.在第 5 行,我们修改了
char *
指向的内容——这应该是合法的。 However,p1
ends up pointing toc
, which isconst
.但是,
p1
最终指向c
,即const
。 This came about in line 4, because*p2
was reallyp1
.这出现在第 4 行,因为
*p2
实际上是p1
。 This was set up in line 3, which is an assignment of a form that is disallowed, and this is exactly why line 3 is disallowed.这是在第 3 行中设置的,这是一个被禁止的表单的分配,这正是第 3 行被禁止的原因。
And as your question is tagged C++ and not C, it even explains what const
qualifiers to use instead:由于您的问题被标记为 C++ 而不是 C,它甚至解释了要使用的
const
限定符:
(C++ has more complicated rules for assigning const-qualified pointers which let you make more kinds of assignments without incurring warnings, but still protect against inadvertent attempts to modify const values. C++ would still not allow assigning a
char **
to aconst char **
, but it would let you get away with assigning achar **
to aconst char * const *
.)(C++ 有更复杂的分配 const 限定指针的规则,这使您可以在不产生警告的情况下进行更多类型的分配,但仍然可以防止无意中尝试修改 const 值。C++ 仍然不允许将
char **
分配给const char **
,但它会让您摆脱将char **
分配给const char * const *
。)
Just since nobody has posted the solution , here:就因为没有人发布解决方案,这里:
char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char * const*ps = a; // no error!
( http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17 for why) ( http://www.parashift.com/c++-faq-lite/const-correctness.html#faq-18.17为什么)
The C++11 draft standard explains this in a note in section 4.4
which says: C++11 草案标准在第
4.4
节的注释中解释了这一点,其中说:
[ Note: if a program could assign a pointer of type T** to a pointer of type const T** (that is, if line #1 below were allowed), a program could inadvertently modify a const object (as it is done on line #2).
[注意:如果程序可以将 T** 类型的指针分配给 const T** 类型的指针(即,如果允许下面的第 1 行),则程序可能会无意中修改 const 对象(因为它已完成)在第 2 行)。 For example,
例如,
int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object }
—end note ]
——尾注]
An interesting related question is Given int **p1 and const int **p2 is p1 == p2 well formed?一个有趣的相关问题是Given int **p1 和 const int **p2 is p1 == p2 wellformed? .
.
Note the C++ FAQ also has an explanation for this but I like the explanation from the standard better.请注意, C++ FAQ对此也有解释,但我更喜欢标准中的解释。
The conforming text that goes with the note is as follows:与注释一致的文本如下:
A conversion can add cv-qualifiers at levels other than the first in multi-level pointers, subject to the following rules:56
转换可以在多级指针的第一个以外的级别添加 cv 限定符,遵循以下规则:56
Two pointer types T1 and T2 are similar if there exists a type T and integer n > 0 such that:
如果存在类型 T 和整数 n > 0 使得两个指针类型 T1 和 T2 相似:
T1 is cv1,0 pointer to cv1,1 pointer to · · · cv1,n−1 pointer to cv1,n T
T1 是 cv1,0 指向 cv1,1 的指针指向 · · · cv1,n−1 指向 cv1,n 的指针 T
and
和
T2 is cv2,0 pointer to cv2,1 pointer to · · · cv2,n−1 pointer to cv2,n T
T2 是 cv2,0 指向 cv2,1 的指针指向 · · · cv2,n−1 指向 cv2,n 的指针 T
where each cvi,j is const, volatile, const volatile, or nothing.
其中每个 cvi,j 是 const、volatile、const volatile 或什么都没有。 The n-tuple of cv-qualifiers after the first in a pointer type, eg, cv1,1, cv1,2, · · · , cv1,n in the pointer type T1, is called the cv-qualification signature of the pointer type.
指针类型中第一个之后的 cv 限定符的 n 元组,例如,指针类型 T1 中的 cv1,1, cv1,2, · · · , cv1,n,称为指针类型的 cv 限定签名. An expression of type T1 can be converted to type T2 if and only if the following conditions are satisfied:
当且仅当满足以下条件时,类型 T1 的表达式才能转换为类型 T2:
- the pointer types are similar.
指针类型相似。
- for every j > 0, if const is in cv1,j then const is in cv2,j , and similarly for volatile.
对于每个 j > 0,如果 const 在 cv1,j 中,那么 const 在 cv2,j 中,对于 volatile 也是如此。
- if the cv1,j and cv2,j are different, then const is in every cv2,k for 0 < k < j.
如果 cv1,j 和 cv2,j 不同,则 const 在每个 cv2,k 中,因为 0 < k < j。
There are two rules here to note:这里有两条规则需要注意:
T*
and U*
if T and U are different types.T*
和U*
之间没有隐式转换。T*
to T const *
implicitly.T*
为T const *
。 ("pointer to T" can be cast to "pointer to const T"). T
is also pointer then this rule can be applied to it as well (chaining).T
也是指针,那么这个规则也可以应用于它(链接)。 So for example:例如:
char**
means: pointer to pointer to char . char**
表示:指向 char 指针的指针。
And const char**
means: pointer to pointer to const char .而
const char**
意味着:指向 const char 指针的指针。
Since pointer to char and pointer to const char are different types that don't differ only in const-ness, so the cast is not allowed.由于指向 char 的指针和指向 const char 的指针是不同的类型,仅在常量性方面不同,因此不允许进行强制转换。 The correct type to cast to should be const pointer to char .
要强制转换的正确类型应该是指向 char 的 const 指针。
So to remain const correct, you must add the const keyword starting from the rightmost asterisk.因此,要保持 const 正确,您必须从最右边的星号开始添加 const 关键字。
So char**
can be cast to char * const *
and can be cast to const char * const *
too.所以
char**
可以转换为char * const *
,也可以转换为const char * const *
。
This chaining is C++ only.此链接仅适用于 C++。 In C this chaining doesn't work, so in that language you cannot cast more than one levels of pointers const correctly.
在 C 中,这种链接不起作用,因此在该语言中,您不能正确地转换多于一层的指针 const。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.