有没有gcc命令行选项可以消除警告:传递参数n会丢弃类型限定符?

3

我试图编译 -Wall -Werror,但它限制了我的风格。

我试图明确指定某些参数为常量,并将它们传递给一个大型库中的非 const 限定函数。

P.S. 我主要是想要清楚地表明某些变量是常量,当处理不使用 const 的库函数时,这样做是好还是坏的 C 风格?


3
你的风格不安全编码?;-) (将英语笑脸表情符号翻译为中文会变为“;-)”) - T.E.D.
也许吧,但我不这么认为。我可能会查看一些源代码,但我相当确定没有任何函数修改值。 - Roman A. Taycher
3个回答

1

使用-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

1

如果您将这些常量作为引用参数或指针传递给程序,那么这些警告可能有很好的理由。您怎么知道这些程序不会修改您的“常量”?这会对您的代码中的其他部分造成什么问题呢?毕竟您说这些变量永远不会改变。

如果您确实确定您所做的事情是安全的,并且没有好的方法来重新编码以消除警告,您可以使用编译器gcc中的pragma关键字关闭一些警告。请尽可能只在一个小的代码区域内这样做,并注明您为什么这样做。

请不要滥用这项特权,否则您可能会被代码警察逮捕,并被判处9个月的社区服务编写Ada代码。这将让您再也不抱怨C语言的警告了。


1
C语言类型系统对 const性质非常宽松。很多人甚至不知道C语言中还有一个 const 关键字。我在C++中经常使用 const_cast,以便能够将数据传递给C库。 - Alexandre C.
1
“const”确实意味着语义只读。技术含义可能不同(另一方面,也可能相同)。 - Šimon Tóth

0

不要使用命令行选项:警告告诉你,你的代码不是 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(并且通常接受许多不正确的输入)。重载函数可以防止您意外使用完全错误的类型,而就地转换则不能。


而且,如果这是C++,代码不仅会给出警告,还会报错。 - Alexandre C.
@Alexandre:说得好。对于C,用常规转换替换const_cast,并使用不同名称的函数进行重载。 - Steve Jessop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接