为了账号安全,请及时绑定邮箱和手机立即绑定

为什么不能在C中将'char **'转换为'const char * const *'?

为什么不能在C中将'char **'转换为'const char * const *'?

C
绝地无双 2019-10-19 14:42:49
以下代码段(正确)在C中给出了警告,并在C ++中给出了错误(分别使用经版本3.4.5和4.2.1测试的gcc和g ++; MSVC似乎无关紧要):char **a;const char** b = a;我可以理解并接受。C ++解决此问题的方法是将b更改为const char * const *,这不允许重新分配指针并阻止您规避const正确性(C ++ FAQ)。char **a;const char* const* b = a;但是,在纯C语言中,更正后的版本(使用const char * const *)仍然发出警告,我不明白为什么。有没有一种方法可以解决这个问题而无需使用演员表?要澄清:1)为什么这会在C语言中生成警告?它应该完全是const安全的,C ++编译器似乎也是如此。2)在说(并让编译器强制执行)我不会修改其指向的字符时接受此char **作为参数的正确方法是什么?例如,如果我想编写一个函数:void f(const char* const* in) {  // Only reads the data from in, does not write to it}我想在char **上调用它,参数的正确类型是什么?
查看完整描述

3 回答

?
千巷猫影

TA贡献1829条经验 获得超7个赞

几年前,我遇到了同样的问题,这让我无休止。


用C表示的规则更简单(即,它们不列出诸如转换char**为的异常const char*const*)。因此,这是不允许的。在C ++标准中,它们包括更多的规则以允许这样的情况。


最后,这只是C标准中的问题。我希望下一个标准(或技术报告)能解决这个问题。


查看完整回答
反对 回复 2019-10-19
?
蓝山帝景

TA贡献1843条经验 获得超7个赞

为了被认为是兼容的,源指针应该在前向间接级别中为const。因此,这将在GCC中向您发出警告:


char **a;

const char* const* b = a;

但这不会:


const char **a;

const char* const* b = a;

另外,您可以强制转换:


char **a;

const char* const* b = (const char **)a;

您将需要使用相同的强制转换来调用函数f()。据我所知,在这种情况下无法进行隐式转换(C ++中除外)。


查看完整回答
反对 回复 2019-10-19
?
白猪掌柜的

TA贡献1893条经验 获得超10个赞

但是,在纯C语言中,这仍然会发出警告,我不明白为什么


您已经确定了问题-此代码不是const正确的。“正确的常量”意味着,除了const_castC样式强制转换删除之外const,您永远const不能通过这些常量指针或引用来修改对象。


const-correctness 的值const在很大程度上用于检测程序员错误。如果您将声明为const,则表示您不应该对其进行修改,或者至少,const只有那些有权使用该版本的人才不能对其进行修改。考虑:


void foo(const int*);

如声明的那样,foo没有权限修改其参数指向的整数。


如果不确定为什么发布的代码不const正确,请考虑以下代码,该代码与HappyDude的代码仅稍有不同:


char *y;


char **a = &y; // a points to y

const char **b = a; // now b also points to y


// const protection has been violated, because:


const char x = 42; // x must never be modified

*b = &x; // the type of *b is const char *, so set it 

         //     with &x which is const char* ..

         //     ..  so y is set to &x... oops;

*y = 43; // y == &x... so attempting to modify const 

         //     variable.  oops!  undefined behavior!

cout << x << endl;

非const类型只能以特定方式转换为const类型,以防止const在没有显式强制转换的情况下对数据类型进行任何规避。


最初声明的对象const特别特殊-编译器可以假定它们永不更改。但是,如果b可以在a不进行强制转换的情况下为其赋值,那么您可能会无意间尝试修改const变量。这不仅会破坏您要求编译器进行的检查,不允许您更改该变量的值,还会使您破坏编译器的优化!


在某些编译器上,这将打印42,在某些编译器上43,则该程序将崩溃。


编辑添加:


HappyDude:您的评论很对。无论是C语言还是正在使用的C编译器,其处理方式const char * const *与C ++语言都根本不同。也许可以考虑仅对此源代码行禁用编译器警告。


查看完整回答
反对 回复 2019-10-19
  • 3 回答
  • 0 关注
  • 1358 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信