【问题标题】:expected expected ‘const char **’ but argument is of type ‘char **’预期预期的“const char **”,但参数的类型为“char **”
【发布时间】:2015-02-28 15:42:37
【问题描述】:

这是我的编译警告:

src/Debugger.c:219:52: warning: passing argument 2 of ‘Debugger_Command[i].Callback’ from incompatible pointer type
                 Debugger_Command[i].Callback(argc, argv);
                                                    ^
src/Debugger.c:219:52: note: expected ‘const char **’ but argument is of type ‘char **’

以下是相关源码:

/* Definition */
typedef void (*Debugger_Callback_t)(int argc, char const * argv[]);
typedef struct tagDebugger_Command_t {
    /* ... */
    Debugger_Callback_t Callback;   /**< Callback */
} Debugger_Command_t;
Debugger_Command_t const Debugger_Command[] = { /* ... */ }

/* Use of the callback where the warning occurred */
char *argv[DEBUGGER_ARG_COUNT];
Debugger_Command[i].Callback(argc, argv);

将非 const 变量作为 const 参数传递有什么问题? 据我了解,这是为了确保不会在函数内部修改字符串。那么为什么会出现警告呢?

编译器:Windows/Cygwin 上的 gcc 版本 4.9.2 (GCC)

【问题讨论】:

    标签: c gcc-warning


    【解决方案1】:

    因为从技术上讲,您可能会通过将非 const 指针传递给 const 指针参数来违反承诺。

    “带走 const-ness 是危险的”

    http://c-faq.com/ansi/constmismatch.html

    这是上面链接的内容:

    您可以使用指向 T 的指针(对于任何类型的 T),其中需要指向 const-T 的指针。但是,允许限定指针类型存在轻微不匹配的规则(显式例外)不会递归应用,而仅在顶层应用。 (const char ** 是指向 const char 的指针,因此该异常不适用。)

    您不能将 char ** 值分配给 const char ** 指针的原因有些晦涩。鉴于 const 限定符完全存在,编译器希望帮助您遵守不修改 const 值的承诺。这就是为什么您可以将 char * 分配给 const char *,但不能反过来:将 const 属性“添加”到一个简单的指针显然是安全的,但将其删除会很危险。但是,假设您执行了以下更复杂的一系列作业:

    const char c = 'x';    /* 1 */
    char *p1;              /* 2 */
    const char **p2 = &p1; /* 3 */
    *p2 = &c;              /* 4 */
    *p1 = 'X';             /* 5 */
    

    在第 3 行,我们将 char ** 分配给 const char **。 (编译器应该抱怨。)在第 4 行,我们将 const char * 分配给 const char *;这显然是合法的。在第 5 行,我们修改了 char * 指向的内容——这应该是合法的。但是,p1 最终指向 c,它是 const。这出现在第 4 行,因为 *p2 实际上是 p1。这是在第 3 行设置的,这是一个不允许的表单分配,这正是第 3 行被禁止的原因。

    将 char ** 分配给 const char **(如第 3 行和原始问题中所示)不会立即产生危险。但它设置了一种情况,在这种情况下 p2 的承诺——最终指向的值不会被修改——无法兑现。

    (C++ 有更复杂的规则来分配 const 限定的指针,这使您可以进行更多类型的分配而不会产生警告,但仍然可以防止无意中尝试修改 const 值。C++ 仍然不允许将 char ** 分配给const char **,但它会让你摆脱将 char ** 分配给 const char * const *。)

    在 C 中,如果您必须分配或传递在第一级间接以外的限定符不匹配的指针,则必须使用显式强制转换(例如,在这种情况下为 (const char **)),尽管与往常一样,需要因为这样的演员表可能表明演员表并没有真正解决的更深层次的问题。

    【讨论】:

    • 这是你给我的一个很好的例子。我想铸造是我唯一的解决方案。
    • 我相信所有人都会同意去掉 const-ness 是很危险的。但是,这种情况正在增加 const-ness。无论如何,链接的常见问题解答确实提供了答案。最好将它的本质带入这个答案,这样这个答案就不是“仅链接”的答案。
    • @CraigMcQueen:感谢您的评论。 (我可能会迟到),但我更新了答案以包含链接的内容
    • 我不明白为什么将char ** 分配给const char ** 是不行的,但是将char * 分配给const char * 是可以的。在他们的示例中,问题在于p1 现在是指向const 数据的非const 指针。你可以很容易地做到char c = 'x'; char *p1 = &amp;c; const char *p2 = p1; *p1 = 'X';。在这种情况下,用解释的话来说,已经违反了p2的数据不会改变的承诺。
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 2020-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-27
    相关资源
    最近更新 更多