【问题标题】:const char** parameter warning about char** argument关于 char** 参数的 const char** 参数警告
【发布时间】:2012-11-13 07:26:53
【问题描述】:

在编译期间调用以下函数:

char* process_array_of_strings(const char** strings);

char** 作为参数传递时,GCC 会抱怨:

note: expected ‘const char **’ but argument is of type ‘char **’

虽然该函数不会更改字符(因此是 const),但它会复制指针数组以修改字符指针本身,因此这里绝对不希望使用常量指针。

编译成功,程序似乎可以运行。那么程序员应该如何处理这个警告呢?

【问题讨论】:

  • 你是怎么调用那个函数的?
  • 啊!现代 c 试图与历史实践保持兼容,同时受益于严格的持续正确性,从而产生美丽的金褐色碎片。
  • @dmckee 是的,它是一个漂亮的 cruft 和所有 :) 但是当函数接受非常量而不是相反时它不应该发出警告吗?
  • 这是常见问题解答:parashift.com/c++-faq/constptrptr-conversion.html。它适用于 C 和 C++。

标签: c char constants


【解决方案1】:

使用强制转换显式转换,编译器会很高兴:

process_array_of_strings((const char**) foo);

在这些情况下,您必须明确表示您知道自己在做什么。

【讨论】:

  • 您的言论和 dmckee 的言论几乎让我相信这是正确的。我确实发生了演员阵容,但想先检查一下。
【解决方案2】:

这就是为什么 char ** 在 C++ 中不会自动转换为 const char ** 的原因,也是 C 编译器在允许时发出警告的原因。

/* This function returns a pointer to a string through its output parameter: */
void get_some_string(const char ** p) {
    /* I can do this because p is const char **, so the string won't be modified. */
    *p = "unchangeable string in program core";
}

void f() {
    char * str;
    /* First, I'll call this function to obtain a pointer to a string: */
    get_some_string(&str);
    /* Now, modify the string: */
    for (char * p = str; *p; p++)
        *p = toupper(*p);
    /* We have just overwritten a constant string in program core (or crashed). */
}

根据您对process_array_of_strings() 所做的描述,它也可以采用const char * const *,因为它既不修改指针也不修改字符(但在别处复制了指针)。在这种情况下,上述情况是不可能的,编译器理论上可以允许您在没有警告的情况下自动将char ** 转换为const char * const *,但这不是语言的定义方式。

所以答案显然是你需要一个演员表(显式)。我写了这个扩展,以便您可以完全理解为什么会出现警告,这在您决定静音时很重要。

【讨论】:

  • 谢谢,帮助理解这个问题的好例子。
  • const char * const * 仍然会引起 GCC 的相同(相似)响应。
  • @Alexey Feldgendler:严格来说,在 C 语言中,这种转换与在 C++ 中一样非法。 C 和 C++ 都应该生成一个“错误”来响应这个转换。只是历史上 C 编译器在这方面更允许。
  • @James Morris:在 C++ 语言中,常量正确性规则已更改。在 C++ 中,将 char ** 转换为 const char *const * 是合法的。在 C 语言中它仍然是非法的。
  • @Alexey Feldgendler:不。这在 C 中是不合法的。在 C 中,这是一个违反约束,即一个错误。形式上,C 语言中没有“只是警告”之类的东西。该实现需要使用任何类型的诊断消息 报告错误。碰巧在这种情况下,编译器决定使用“警告”类型的诊断消息报告此错误。
猜你喜欢
  • 2016-05-29
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 2011-04-17
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多