为什么将“指针到非常量指针”转换为不合法?指向“指向 const 指针的指针”

发布于 2024-08-20 10:53:14 字数 248 浏览 8 评论 0原文

将非常量指针转换为常量指针是合法的。

那么为什么将指向非 const 的指针转换为指向 const 的指针是不合法的呢?

例如,为什么下面的代码是非法的:

char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char **ps = a; // error!

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?

E.g., why is the following code illegal:

char *s1 = 0;
const char *s2 = s1; // OK...
char *a[MAX]; // aka char **
const char **ps = a; // error!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沧桑㈠ 2024-08-27 10:53:14

从标准来看:

const char c = 'c';
char* pc;
const char** pcc = &pc;   // not allowed
*pcc = &c;
*pc = 'C';                // would allow to modify a const object

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
新雨望断虹 2024-08-27 10:53:14

忽略您的代码并回答您问题的原理,请参阅 comp.lang.c FAQ 中的此条目:
为什么我不能将 char ** 传递给需要 const char ** 的函数?

无法将 char ** 值分配给 const char ** 指针的原因有些模糊。鉴于 const 限定符确实存在,编译器希望帮助您遵守不修改 const 值的承诺。这就是为什么您可以将 char * 分配给 const char *,但反之则不然:“添加”const 显然是安全的-ness 是一个简单的指针,但是把它拿走是危险的。但是,假设您执行了以下一系列更复杂的作业:

const char c = 'x'; /* 1 */
字符*p1; /* 2 */
const char **p2 = &p1; /* 3 */
*p2 = &c; /* 4 */
*p1 = 'X'; /* 5 */

在第 3 行中,我们将 char ** 分配给 const char **。 (编译器应该抱怨。)在第 4 行,我们将一个 const char * 分配给一个 const char * ;这显然是合法的。在第 5 行中,我们修改了 char * 指向的内容——这应该是合法的。但是,p1 最终指向 c,即 const。这发生在第 4 行,因为 *p2 实际上是 p1。这是在第 3 行中设置的,这是不允许的表单赋值,这正是第 3 行不允许的原因。

由于您的问题被标记为 C++ 而不是 C,它甚至解释了要使用什么 const 限定符:

(C++ 对于分配 const 限定指针有更复杂的规则,这些规则允许您进行更多类型的分配而不会产生警告,但仍然可以防止无意中尝试修改 const 值。C++ 仍然不允许分配 char * *const char **,但它可以让您将 char ** 分配给 const char * const *< /代码>。)


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 **?

The reason that you cannot assign a char ** value to a const char ** pointer is somewhat obscure. Given that the const qualifier exists at all, the compiler would like to help you keep your promises not to modify const values. That's why you can assign a char * to a const 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. 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 a const char **. (The compiler should complain.) In line 4, we assign a const char * to a const char *; this is clearly legal. In line 5, we modify what a char * points to--this is supposed to be legal. However, p1 ends up pointing to c, which is const. This came about in line 4, because *p2 was really 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.

And as your question is tagged C++ and not C, it even explains what const qualifiers to use instead:

(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 a const char **, but it would let you get away with assigning a char ** to a const char * const *.)

原来分手还会想你 2024-08-27 10:53:14

由于没有人发布解决方案,这里:

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 了解原因)

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)

离旧人 2024-08-27 10:53:14

C++11 标准草案4.4 节的注释中解释了这一点,其中写道:

[ 注意:如果程序可以将 T** 类型的指针分配给指针
const T** 类型(即,如果允许下面的第 1 行),一个程序
可能会无意中修改 const 对象(如第 2 行所示)。
例如,

int main() {
const char c = 'c';
字符* PC;
const char** pcc = &pc; // #1: 不允许
*pcc = &c;
*pc = 'C'; // #2: 修改 const 对象
}

——尾注]

一个有趣的相关问题是 给定 int **p1 和 const int **p2 是 p1 == p2 格式良好?

请注意 C++ FAQ 对此也有解释,但我喜欢标准的解释更好。

注释中的一致文本如下:

转换可以在第一个级别以外的级别添加 cv 限定符
多级指针,遵守以下规则:56

<块引用>

如果存在类型 T 且存在,则两个指针类型 T1 和 T2 相似
整数n> 0 这样:

<块引用>

T1 是 cv1,0 指向 cv1 的指针,1 指向...的指针 cv1,n−1 指向 cv1,n 的指针

<块引用>

T2 是 cv2,0 指向 cv2 的指针,1 指向…的指针 cv2,n−1 指向 cv2 的指针,n T

其中每个 cvi,j 都是 const、易失性、常量易失性或什么都不是。这
指针类型中第一个之后的 n 元组 cv 限定符,例如,
cv1,1, cv1,2,···, cv1,n 在指针类型 T1 中,被称为
指针类型的 cv 限定签名。类型的表达式
当且仅当满足以下条件时,T1 才能转换为 T2 类型
满意:

  • 指针类型相似。
  • 对于每个 j > 0,如果 const 位于 cv1,j 中,则 const 位于 cv2,j 中,对于 volatile 也是如此。
  • 如果 cv1,j 和 cv2,j 不同,则 const 存在于每个 cv2,k 中(0 <<<)。 k< j.

The C++11 draft standard explains this in a note in section 4.4 which says:

[ 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).
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?.

Note the C++ FAQ also has an explanation for this but I like the explanation from the standard better.

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

Two pointer types T1 and T2 are similar if there exists a type T and
integer n > 0 such that:

T1 is cv1,0 pointer to cv1,1 pointer to · · · cv1,n−1 pointer to cv1,n
T

and

T2 is cv2,0 pointer to cv2,1 pointer to · · · cv2,n−1 pointer to cv2,n T

where each cvi,j is const, volatile, const volatile, or nothing. The
n-tuple of cv-qualifiers after the first in a pointer type, e.g.,
cv1,1, cv1,2, · · · , cv1,n in the pointer type T1, is called the
cv-qualification signature of the pointer type. An expression of type
T1 can be converted to type T2 if and only if the following conditions
are satisfied:

  • 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.
  • if the cv1,j and cv2,j are different, then const is in every cv2,k for 0 < k < j.
残龙傲雪 2024-08-27 10:53:14

这里有两个规则需要注意:

  • 如果 T 和 U 是不同的类型,则 T*U* 之间没有隐式转换。
  • 您可以将 T* 隐式转换为 T const *。 (“指向 T 的指针”可以转换为“指向 const T 的指针”)。在 C++ 中,如果 T 也是指针,那么该规则也可以应用于它(链接)。

例如:

char** 表示:指向 char 的指针

const char** 的意思是:指向 const char 的指针

由于指向 char 的指针指向 const char 的指针是不同的类型,仅在常量方面不同,因此不允许进行强制转换。正确的转换类型应该是指向 char 的 const 指针

因此,为了保持 const 正确,您必须从最右边的星号开始添加 const 关键字。

因此,char** 可以转换为 char * const *,也可以转换为 const char * const *

此链接仅适用于 C++。在 C 中,这种链接不起作用,因此在该语言中,您无法正确转换多于一层的指针 const。

There are two rules here to note:

  • There are no implicit casts between T* and U* if T and U are different types.
  • You can cast T* to T const * implicitly. ("pointer to T" can be cast to "pointer to const T"). In C++ if T is also pointer then this rule can be applied to it as well (chaining).

So for example:

char** means: pointer to pointer to char.

And const char** means: pointer to pointer to 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. The correct type to cast to should be const pointer to char.

So to remain const correct, you must add the const keyword starting from the rightmost asterisk.

So char** can be cast to char * const * and can be cast to const char * const * too.

This chaining is C++ only. In C this chaining doesn't work, so in that language you cannot cast more than one levels of pointers const correctly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文