我正在尝试构建M-SIM架构模拟器,但是当我运行make工具时,gcc报告了这个错误(甚至不是一个警告)
注意:期望的是'char *'类型的参数,但实际传入的是'const char *'类型。
为什么现在这被视为错误了呢?有没有任何标志可以绕过此检查?
这是一个错误,因为将一个const char*
参数传递给接受char*
参数的函数会违反const正确性;它会允许你修改一个const
对象,这将破坏const
的整个目的。
例如,这个C程序:
#include <stdio.h>
void func(char *s) {
puts(s);
s[0] = 'J';
}
int main(void) {
const char message[] = "Hello";
func(message);
puts(message);
return 0;
}
使用gcc编译器将产生以下编译时诊断:
c.c: In function ‘main’:
c.c:10:5: warning: passing argument 1 of ‘func’ discards qualifiers from pointer target type
c.c:3:6: note: expected ‘char *’ but argument is of type ‘const char *’
最终的消息被标记为"note",因为它提到了(完全合法的)func()
声明,并解释了这是警告所指的参数声明。const char *
到char *
的隐式转换。Hello
Jello
即使我将message
声明为const
,该函数仍然可以修改它,这表明了问题所在。
由于gcc没有将其视为致命错误,因此无需抑制任何诊断消息。代码仍可能正常工作(例如,如果该函数无意修改任何内容)。但警告存在是有原因的,您或M-SIM架构模拟器的维护者应该查看此问题。
(将字符串文字传递给func()
不会触发这些诊断消息,因为C不将字符串文字视为const
。(尝试修改字符串文字的行为是未定义的。)这是出于历史原因。gcc确实具有一个选项-Wwrite-strings
,可使其将字符串文字视为const
;这实际上违反了C标准,但它可以是一个有用的检查。)
正如我在评论中提到的,如果您能向我们展示触发诊断消息的代码,那将很有帮助。
我甚至下载并构建了M-SIM架构模拟器,但我没有看到该特定消息。
strlen
接受一个const char*
,但你可以传递一个指向可修改数组的char*
。你可以随意修改数组,但strlen
不会修改它。 - Keith Thompsonconst
修饰的类型的指针不能隐式转换成非const
修饰的类型的指针。必须通过显式转换来进行,例如:
const int *p;
int *q = const_cast(p);
foo((char *)bar)
bar
实际上是一个常量字符指针,那么这可能是危险的。 - shinkou在函数调用中(使用原型定义的函数),首先将参数转换为参数类型,就像通过赋值一样。
您可以将类型为char *
的值分配给类型为const char *
的对象,但不能将const char *
值分配给char *
对象。
这个约束出现在赋值运算符的约束中:
(C99, 6.5.16.1p1) "应满足以下条件之一:[...] - 两个操作数都是指向限定或未限定版本的兼容类型的指针,并且左边指向的类型具有右边指向的类型的所有限定符;"
这个约束允许第一个赋值,但禁止第二个。
使用类型const char *
声明指针意味着您不会修改指针所指向的对象。因此,您可以将指针分配为char *
类型的值,这只意味着对象不会通过const char *
指针进行修改。
但是,声明类型为char *
的指针意味着您可以修改指针所指向的对象。将其分配为const char *
的值是没有意义的。
请记住,在C中,const
并不意味着常量,而是只读。在指针类型之前放置的const
限定符表示您承诺不通过这些指针类型的对象修改对象。
strdup()
)strdup()
分配了空间,不要忘记在使用完后将其释放。 - Jonathan Leffler
const
类型。同时,请向我们展示(复制粘贴)完整的错误信息;我记得gcc的错误信息不应该以“note”开头。 - Keith Thompson