C抱怨将char**值传递给函数,使用char const*const*const,但C++没有

 直由飞翔_447 发布于 2023-02-13 10:11

在解释和创建函数参数的类型时,我很难理解为什么C++比C更"放松"的行为.

C做世界上最简单的事情,它坚持你写的东西就是这样,另一方面,C++以一种我无法理解的扭曲方式运作.

例如,流行的argv是一个char* []传递给函数的时候变成了char**,我真的不明白为什么,我期待和"想要" char * const *但是我得到了这种行为.

您还可以阅读PDF中讨论C和C++之间差异的文章,文章也以这句话结尾:

虽然C++在确定函数签名时会忽略参数声明中的顶级cv限定符,但它并不完全忽略这些cv限定符.

因为我在网上找不到这个问题(嵌入式系统编程 - 2000年2月,这个老问题是免费的),我想知道这句话可能意味着什么.

有人可以解释为什么这种行为是它在C++中的行为?

编辑:

我的一个例子是

#include 

void foo(int argc, const char *const *const argv) {
  printf("%d %s\n", argc, argv[0]);
}

int main(int argc, char *argv[]) {
  foo(argc, argv);
  return (0);
}

如果你编译它,gcc 4.8.1你得到预期的错误

gcc cv_1.c 
cv_1.c: In function ‘main’:
cv_1.c:8:3: warning: passing argument 2 of ‘foo’ from incompatible pointer type [enabled by default]
   foo(argc, argv);
   ^
cv_1.c:3:6: note: expected ‘const char * const* const’ but argument is of type ‘char **’
 void foo(int argc, const char *const *const argv) {
      ^

此输出隐含了argv被解释为的事实char**

2 个回答
  • 函数参数可以通过值或引用传递.在引用的情况下,没有顶级限定符,因此我们可以忽略该情况.

    对于按值参数,顶级限定符仅影响副本,并且完全独立于用于复制构造该参数的原始值.如果未从签名中删除顶级限定符,则以下两个函数将是有效且不同的重载:

    void f(int       i);
    void f(int const i);
    

    现在的问题是,如果f(1)应该选择两个重载中的哪一个?这里的问题是参数是否为const不会影响它的构造,因此编译器永远无法解析哪个是正确的重载.解决方案很简单:在签名中,顶级限定符被删除,两者都是相同的函数.

    2023-02-13 10:12 回答
  • 您链接的PDF文章包含许多关于C和C++在处理顶级cv限定符时的差异的错误陈述.这些差异要么不存在,要么与本文所暗示的不同.

    实际上,在确定函数签名和函数类型时,C和C++都有效地忽略了函数参数声明中的顶级cv限定符.C和C++语言标准中的措辞(以及底层机制)在概念上可能不同,但最终结果在两种语言中都是相同的.

    C++确实直接确定功能类型时对参数忽略顶层cv修饰符,如在8.3.5/5描述:"生产参数类型的列表之后,修改的参数类型的任何顶层CV-限定符删除时形成功能类型."

    C不依赖于兼容类型的C特定概念,而是直接忽略此类限定符.它表示仅在参数的顶级cv限定符中不同的函数类型是兼容的,这对于所有方法和目的意味着它们是相同的.在6.7.5.3/15的函数类型的相容性的定义表示:"以类型兼容性和复合型的确定,[...]与限定的类型声明的每个参数取为具有不合格其声明的类型的版本".

    链接的PDF文章指出,在C中,以下声明序列是非法的

    void foo(int i);
    void foo(const int i);
    

    实际上它在C语言中是完全合法的.C只需要在同一范围内的同一实体的所有声明都使用兼容类型(6.7/4).上面的两个声明是兼容的,这意味着它们只是合法地重新声明相同的功能.(在C++中,上述声明也是合法的,它们也重新声明了相同的功能.)

    对于其他示例,在C和C++中,以下初始化有效

    void foo(const int i);
    void bar(int i);
    
    void (*pfoo)(int) = foo;       // OK
    void (*pbar)(const int) = bar; // OK
    

    同时,在确定函数参数的局部变量类型时,C和C++ 同样考虑了顶级cv限定符.例如,在C和C++中,以下代码都是格式错误的

    void foo(const int i) {
      i = 5; // ERROR!
    }
    

    在C和C++中,在其参数上使用一个顶级cv限定声明的函数可以稍后使用其参数的完全不同的cv限定来定义.顶级cv资格的任何差异都不构成C++中的函数重载.


    此外,您反复提到这char *[]被解释为char **相关的东西.我没有看到相关性.在函数参数列表中,T []声明总是等同于T *声明.但这与顶级cv-qualifiers完全无关.

    同时,编辑中的代码示例无法编译,原因与顶级cv限定符无关.它不能编译,因为有一个从没有隐式转换char **const char *const *C语言编写.请注意,此转换不涉及任何顶级cv限定符,也不关心任何顶级cv限定符.const影响此转换的限定符仅出现在第一个和第二个间接层上.

    这确实涉及C和C++之间的差异.在C和C++中char **,const char **不允许隐式转换为to (例如,请参见此处).但是,C++允许隐式转换char **,const char *const *而C仍然没有.你可以在这里阅读更多相关信息.但请注意,在所有这些情况下,顶级cv限定符完全无关紧要.他们根本没有任何作用.

    2023-02-13 10:13 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有