以下是编译警告:
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)
答案 0 :(得分:7)
因为从技术上讲,你可能会通过将非const指针传递给const指针参数来破坏承诺。
&#34;带走const-ness&#34;
是危险的http://c-faq.com/ansi/constmismatch.html
以下是上述链接的内容:
您可以使用指向T的指针(对于任何类型T),其中指向const-T指针。但是,允许在限定指针类型中轻微不匹配的规则(显式异常)不是递归应用的,而是仅在顶层应用。 (const char **是指向const-char的指针,因此异常不适用。)
您无法将char **值分配给const char **指针的原因有点模糊。鉴于const限定符完全存在,编译器希望帮助您保证不修改const值。这就是为什么你可以将一个char *分配给一个const char *,而不是相反的方式:它可以明显安全地“添加”#39;&#39;坚持一个简单的指针,但把它带走是危险的。但是,假设您执行了以下更复杂的分配系列:
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 **分配给a const char **,但是它可以让你把char **赋给const char * const *。)
在C中,如果必须分配或传递在第一级间接之外具有限定符不匹配的指针,则必须使用显式强制类型转换(例如(例如(const char **)),尽管一如既往需要对于这样的演员阵容可能表明演员没有真正解决的更深层次的问题。