为什么C没有允许焦炭**隐式转换为const char * const的*(和C ++一样)? [英] Why C doesn't allow implicit conversion from char ** to const char *const * (and C++ does)?

查看:480
本文介绍了为什么C没有允许焦炭**隐式转换为const char * const的*(和C ++一样)?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道,从的char ** 来的隐式转换为const char ** 无法做到的,为什么,而且转换为 char * const的* 的作品。见链接,说明在该底部。

I know implicit conversion from char ** to const char ** cannot be done and why, and that the conversion to char *const * works. See bottom for links to explanation on that.

这一切都有道理除了一个特别的事情。所以,我有以下的code:

It all makes sense apart from one particular thing. So I have the following code:

#include <stdio.h>

void
print(const char *const*param)
{
    printf("%s\n", param[0]);
}

int
main(int argc, char **argv)
{
    print(argv);
    return 0;
}

如果我编译这是一个C ++ code,它编译相当的精细。但是,如果同一code编译为C $ C $只有c,我得到一个错误(当然,一个警告,但是让我们假设 -Werror ,即警告视为错误)。

If I compile this as a C++ code, it compiles quite fine. However, if the same code is compiled as a C code only, I get an error (well, a warning, but let's suppose -Werror, i.e. treat warnings as errors).

GCC:

test.c: In function ‘main’:
test.c:12:11: warning: passing argument 1 of ‘print’ from incompatible pointer type [-Wincompatible-pointer-types]
     print(argv);
           ^
test.c:4:1: note: expected ‘const char * const*’ but argument is of type ‘char **’
 print(const char *const*param)
 ^

铛:

test.c:12:11: warning: passing 'char **' to parameter of type 'const char *const *' discards qualifiers in nested pointer types [-Wincompatible-pointer-types-discards-qualifiers]
    print(argv);
          ^~~~
test.c:4:25: note: passing argument to parameter 'param' here
print(const char *const*param)
                        ^

两种行为是标准无关,也编译器无关。我试过各种标准既 GCC

有两个原因调查。首先,我想了解是否有差异,其次,我有什么都不做与指针的任何层的功能,我需要它能够与为const char工作** 以及 char * const的* 的char ** 。明确铸造每次通话不维护。而且我不知道的函数原型应该怎么样子。

There are two reasons for this inquiry. Firstly, I want to understand whether there is a difference and, secondly, I have a function that does nothing with any layer of the pointers and I need it to be able to work with const char ** as well as char *const * and char **. Explicitly casting each call is not maintainable. And I have no idea how should the function prototype look like.

这是开始了我的好奇心的问题:
<一href=\"https://stackoverflow.com/questions/7016098/implicit-conversion-from-char-to-const-char\">Implicit从焦炭转化**为const char **

This is the question that started my curiosity: Implicit conversion from char** to const char**

这是的char ** = GT另一个很好的解释;为const char ** 的问题:
http://c-faq.com/ansi/constmismatch.html

如果链接混淆了与此相关的问题,请随时编辑出来。

If the links are confusing related to this question, feel free to edit them out.

推荐答案

C和C ++在这方面有所不同。我没有回答,为什么C ++是比较慷慨的,其他比C ++的行为在我看来是正确的。

C and C++ are different in this respect. I don't have an answer to why C++ is more generous, other than that the C++ behaviour seems to me to be correct.

ç根本不允许间接常量的转换。这是一个保守的,易于实施的限制,与不幸的后果,你不能提供的char * [] 来期待字符常量的函数*常量* 。该限制是与教派; 6.3.2.3条第2款,这根本就不是递归的:

C simply doesn't allow indirect const conversion. That is a conservative, easy-to-implement restriction, with the unfortunate consequence that you cannot provide char*[] to a function expecting char const* const*. The restriction is in §6.3.2.3, paragraph 2, and it is simply not recursive:

有关的任​​何限定,指向一个非 - -qualified类型可以被转换为指针该类型的 -qualified版本;存储在原始和转换后的指针值应等于比较

For any qualifier q, a pointer to a non-q-qualified type may be converted to a pointer to the q-qualified version of the type; the values stored in the original and converted pointers shall compare equal.

C ++允许按照一套较为复杂的配方,与教派的转换; 4.4 [conv.qual]第3款是允许的转换

C++ allows conversions according to a somewhat complex formulation in §4.4 [conv.qual], paragraph 3. It is permitted to convert

T CV <子> N P <子> N-1 CV <子> N-1 &hellip; P 1 CV 1 P 0 CV 0
&RARR;
T CV <子> N P <子> N-1 CV <子> N-1 &hellip; P 1 CV 1 P 0 CV 0

T cvn Pn-1cvn-1 … P1cv1 P0cv0T cv'n Pn-1cv'n-1 … P1cv'1 P0cv'0

(其中 T 是一类; P 1 &hellip; P <子> N 是指针/数组类型的构造函数,每个 CV 0 &hellip; CV <子> N 一些可能的空子集常量挥发性

(where T is a type; P1…Pn are pointer/array type constructors, and each cv0…cvn is some possibly empty subset of const and volatile)

,条件是:


  1. 对于每个 K&GT; 0 CV <子> K CV的一个子集<子> K (所以你不能删除常量挥发性)和

如果 CV <子> K CV <子> K 一些 K&GT; 0 ,下面所有的 CV I&GT; k 包括常量

If cvk and cv'k differ for some k > 0, all the following cv'i>k include const.

在实际的标准,即前pression逆转;我把它放在声明的顺序,而在标准它是在指针/数组构造函数的应用顺序。我没有更改编号的方向,虽然,这就是为什么他们的编号从右到左。我也留下了一些细节 - 例如,它不是绝对必需的两个 T s到是相同的 - 但我认为它给人的意图想法

In the actual standard, that expression is reversed; I put it in the order of declaration, whereas in the standard it is in order of application of the pointer/array constructors. I didn't change the direction of the numbering, though, which is why they are numbered right to left. I also left out some details -- for example, it's not strictly necessary for the two Ts to be identical -- but I think it gives an idea of the intention.

有第一限制的解释是相当明显。第二个限制prevents在C FAQ,其中常量指针可能会被存储到一个非描述的问题 - 常量指针对象,并随后用变异的常量对象指向。

The explanation for the first restriction is reasonably obvious. The second restriction prevents the problem described in the C FAQ, where a const pointer might be stored into a non-const pointer object, and then subsequently used to mutate the const object it points to.

的底线是,在C ++中,你的原型为const char * const的*参数将与参数类型的工作的char ** 为const char ** ,甚至 char * const的* ,但在C只有最后一个将工作而不会警告,它是最有用的。我知道(不是切换到C ++等)的唯一的解决方法是忽略警告。

The bottom line is that in C++, your prototype const char *const * param will work with arguments of type char**, const char**, or even char*const*, but in C only the last one will work without warning, and it is the least useful. The only workaround I know of (other than switching to C++) is to ignore the warning.

有关它的价值,有一个在的部分理由在的POSIX规范EXEC * 接口的有关Posix的,这是使用的char * [] 为原型上和文字指出,这些是不变的:(强调)

For what it's worth, there is a note in the Rationale section of the Posix specification of the exec* interfaces about the problem this causes for these prototypes, and the workaround selected by Posix, which is to use char*[] as the prototype and textually note that these are constant: (emphasis added)

有关语句的argv [] envp [] 是常量包含作出明确为未来的作家语言绑定,这些对象是完全不变。 由于ISO C标准的限制,这是不可能说出标准C这一想法。指定 const的两个级别企业资质为在的argv [] envp [] 的执行函数的参数似乎是自然的选择,因为这些功能不修改指针的存储阵列或到的功能点,但这将禁止现有正确的code中的字符。相反,只有指针数组记为常数。

The statement about argv[] and envp[] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. Due to a limitation of the ISO C standard, it is not possible to state that idea in standard C. Specifying two levels of const-qualification for the argv[] and envp[] parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant.

有一个有用的兼容性图表下面的那款,我没有,因为这个网站的格式限制的报价。

There's a useful compatibility chart following that paragraph, which I didn't quote because of the formatting limitations of this site.

这篇关于为什么C没有允许焦炭**隐式转换为const char * const的*(和C ++一样)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆