prev up next   top/contents search

comp.lang.c FAQ 列表· 问题 11.10

Q为什么我不能传递一个char **给需要const char **?


A你可以使用指向 T 的指针(对于任何类型 T)来代替指向 const T 的指针。然而,允许限定指针类型有轻微不匹配的规则(一个显式的例外)不是递归应用的,只在顶层应用。(const char **是指向 const char 的指针的指针,因此该例外不适用。)

你不能将一个char **值赋给一个const char **指针的原因有些晦涩。考虑到const限定符的存在,编译器希望帮助你遵守不修改const值的承诺。这就是为什么你可以分配一个char *转换为const char *,但不能反过来:将const-性“添加”到一个简单指针上是明显安全的,但移除它则是危险的。然而,假设你执行了以下更复杂的赋值系列

	const char c = 'x';		/* 1 */
	char *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 行被不允许的*原因*。

赋值一个char **转换为const char **(如第 3 行以及原问题中)并非立即危险。但它建立了一种情况,使得p2的承诺——最终指向的值不会被修改——无法兑现。

(C++ 对赋值const-限定指针有更复杂的规则,允许你在不产生警告的情况下进行更多种类的赋值,但仍能防止无意中修改const值。C++ 仍然不允许赋值一个char **转换为const char **,但它会允许你赋值一个char **转换为const char * const *.)

在 C 语言中,如果你必须在间接层级非第一层级的地方赋值或传递具有限定符不匹配的指针,你必须使用显式转换(例如(const char **)在这种情况下),尽管正如常言道,需要这样的转换可能表明存在一个更深层次的问题,而转换本身并没有真正解决。

参考:ISO Sec. 6.1.2.6, Sec. 6.3.16.1, Sec. 6.5.3
H&S Sec. 7.9.1 pp. 221-2


prev up next   contents search
关于此 FAQ 列表   关于 Eskimo   搜索   反馈   版权

Eskimo North 托管