我试图编译 -Wall -Werror,但它限制了我的风格。
我试图明确指定某些参数为常量,并将它们传递给一个大型库中的非 const 限定函数。
P.S. 我主要是想要清楚地表明某些变量是常量,当处理不使用 const 的库函数时,这样做是好还是坏的 C 风格?
我试图编译 -Wall -Werror,但它限制了我的风格。
我试图明确指定某些参数为常量,并将它们传递给一个大型库中的非 const 限定函数。
P.S. 我主要是想要清楚地表明某些变量是常量,当处理不使用 const 的库函数时,这样做是好还是坏的 C 风格?
使用-Wno-ignored-qualifiers
开关。
有时,当使用-Wall -Wextra -Werror
编译(我也这样做,因为它是非常好的实践),您会面临反复出现的警告,您可能希望在整个项目或每个源文件的基础上禁用某些警告。例如,我经常在我的项目中禁用-Wno-long-long
。这不是坏习惯,因为您知道自己在做什么,并且不想控制第三方代码。
但是,据我所知,您正在尝试禁用特定代码部分的警告,否则它将破坏您在各处放置const
的努力。在这种情况下,请执行以下操作:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wignored-qualifiers"
OffendingThirdPartyFunction(MyConstParam);
#pragma GCC diagnostic pop
或者也可以(未经测试,我不知道在哪里放分号,而且我在工作中没有一个可用的GCC)
#define NO_WARNING(expr) \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wignored-qualifiers\"") \
expr \
_Pragma("GCC diagnostic pop")
NO_WARNING(OffendingThirdPartyFunction(MyConstParam));
或者,您可以使用强制类型转换。这是目前最具可移植性的解决方案。
OffendingThirdPartyFunction((param_t*)MyConstParam);
-Wno-ignored-qualifiers
只有一个目的:抑制关于限定符的警告,这些限定符由于被放置在不应该存在的位置(例如函数返回值)而没有实际效果。 (为什么会有这样的规则,我不知道,希望能有所改变!) - Jeff Learman如果您将这些常量作为引用参数或指针传递给程序,那么这些警告可能有很好的理由。您怎么知道这些程序不会修改您的“常量”?这会对您的代码中的其他部分造成什么问题呢?毕竟您说这些变量永远不会改变。
如果您确实确定您所做的事情是安全的,并且没有好的方法来重新编码以消除警告,您可以使用编译器gcc中的pragma关键字关闭一些警告。请尽可能只在一个小的代码区域内这样做,并注明您为什么这样做。
请不要滥用这项特权,否则您可能会被代码警察逮捕,并被判处9个月的社区服务编写Ada代码。这将让您再也不抱怨C语言的警告了。
const
性质非常宽松。很多人甚至不知道C语言中还有一个 const
关键字。我在C++中经常使用 const_cast
,以便能够将数据传递给C库。 - Alexandre C.不要使用命令行选项:警告告诉你,你的代码不是 const-safe。没错,你的代码确实不是 const-safe,虽然这是你所使用的库编写人的责任。
如果你禁用了警告,即使你编写不安全的代码并且是你自己的问题,你也不会再收到警告。
相反,每当库函数之一接受一个指向非const的指针,但保证不会修改指针所指对象时,将const-ness从指针中移除,并传递该指针。强制转换在代码中充当记录,证明你(程序员)声明不会发生任何无效操作,即使类型系统不能证明,应该添加注释。
例如:
// in this library
void print_int(int *p) { printf("%d\n", *p); }
void set_int(int *p) { *p = 6; }
// your code
const int n = 5;
print_int((int*)(&n)); // warning suppressed for this call only,
// having carefully checked the print_int docs.
// further down your code
set_int(&n); // You *want* the compiler to stop this!
或者如果你有足够的时间(因为你有很多这样的调用),可以编写包装器来处理有问题的库函数:
void print_int_const(const int *p) { print_int((int*)(p)); }
// but no wrapper for set_int
请注意,强制类型转换也会移除volatile
(并且通常接受许多不正确的输入)。重载函数可以防止您意外使用完全错误的类型,而就地转换则不能。