ner*_*ert 15 c c++ gcc const clang
我知道,从隐式转换char **到const char **无法做到的,为什么,而且转化为char *const *作品.请参阅底部以获取有关该说明的链接.
除了一件特别的事情外,这一切都是有道理的 所以我有以下代码:
#include <stdio.h>
void
print(const char *const*param)
{
printf("%s\n", param[0]);
}
int
main(int argc, char **argv)
{
print(argv);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我将其编译为C++代码,它编译得非常好.但是,如果相同的代码仅编译为C代码,我会收到错误(好吧,警告,但我们假设-Werror,即将警告视为错误).
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)
^
Run Code Online (Sandbox Code Playgroud)
铛:
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)
^
Run Code Online (Sandbox Code Playgroud)
这两种行为都是标准无关的,也是独立于编译器的.我试着用这两种不同的标准gcc和clang.
这项调查有两个原因.首先,我想了解是否有差异,其次,我有什么都不做与指针的任何层的功能,我需要它能够与合作const char **,以及char *const *和char **.显式地转换每个调用是不可维护的.我不知道函数原型应该怎么样.
这是引起我好奇心的问题: 从char**隐式转换为const char**
以下是该char ** => const char**问题的另一个很好的解释:http:
//c-faq.com/ansi/constmismatch.html
如果链接与此问题相关,请随意编辑它们.
ric*_*ici 13
C和C++在这方面是不同的.我没有回答为什么C++更慷慨,除了C++行为在我看来是正确的.
C根本不允许间接const转换.这是一种保守的,易于实施的限制,伴随着你无法提供char*[]给期望功能的不幸后果char const* const*.限制在§6.3.2.3第2段中,它根本不是递归的:
对于任何限定符
q,指向非q限定类型的指针可以转换为指向q该类型的限定版本的指针; 存储在原始指针和转换指针中的值应相等.
C++允许根据§4.4[conv.qual]第3段中的某种复杂的公式进行转换.允许转换
T cvn Pn-1cvn-1 … P1cv1 P0cv0
⇒
T cv'n Pn-1cv'n-1 … P1cv'1 P0cv'0
(where T是一个类型; 是指针/数组类型构造函数,每个都是一些可能是空的子集和)P1…Pncv0…cvnconstvolatile
规定:
对于每一个k > 0,是一个子集(所以你不能删除a 或a ),和cvkcv'kconstvolatile
如果和有些不同,以下所有内容包括.cvkcv'kk > 0cv'i>kconst
在实际标准中,这种表达方式是相反的; 我把它放在声明的顺序,而在标准中它是按指针/数组构造函数的应用顺序.但是,我没有改变编号的方向,这就是为什么它们从右到左编号.我也省略了一些细节 - 例如,两者T的相同并不是绝对必要的- 但我认为它给出了意图的概念.
对第一个限制的解释是相当明显的.第二个限制可以防止C FAQ中描述的问题,其中const指针可能存储在非const指针对象中,然后用于改变const它指向的对象.
底线是,在C++中,你的原型const char *const * param将与参数类型的工作char**,const char**或甚至char*const*,但在C只有最后一个没有预警的工作,它是最有用的.我所知道的唯一解决方法(除了切换到C++之外)就是忽略警告.
对于它的价值,在Posix规范exec*的基本原理部分中有一个关于这些原型引起的问题的接口的注释,以及Posix选择的解决方法,它char*[]用作原型和文本说明这些是常量:(重点补充)
包含有关
argv[]和envp[]成为常量的语句,以明确未来的语言绑定编写者,这些对象是完全不变的.由于ISO C标准的限制,不可能在标准C中陈述该想法.为exec函数和参数指定两个级别的const资格似乎是自然的选择,因为这些函数不是修改指针数组或函数指向的字符,但这将禁止现有的正确代码.相反,只有指针数组被标记为常量.argv[]envp[]
在该段落之后有一个有用的兼容性图表,由于此站点的格式限制,我没有引用该图表.