我正在修复我继承的遗留项目中的编译器警告。新编译器是 gcc 版本 4.8.5 20150623 (Red Hat 4.8.5-4) (GCC)。
他们有很多代码如下:
#include <cstdio>
#include <cstring>
struct foobar
{
char field1[10];
char field2[5];
};
int main()
{
struct foobar foo;
memset(&foo, ' ', sizeof(foo));
strncpy(foo.field1, "1234567890", sizeof(foo.field1));
// Produces warning
printf("[%.*s]", sizeof(foo.field1), foo.field1);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这会产生警告消息:
1_test.c: In function ‘int main()’:
1_test.c:16:49: warning: field precision specifier ‘.*’ expects argument of type ‘int’, but argument 2 has type ‘long unsigned int’ [-Wformat=]
printf("[%.*s]", sizeof(foo.field1), foo.field1);
Run Code Online (Sandbox Code Playgroud)
这对我来说似乎是错误的,因为 '.*' 应该期待 size_t 但显然它没有......
除了必须执行以下操作之外,还有没有办法在全球范围内解决此问题:
// Fixes
printf("[%.10s]", foo.field1);
// Fixes
printf("[%.*s]", static_cast<int>(sizeof(foo.field1)), foo.field1);
Run Code Online (Sandbox Code Playgroud)
你总是有一些不有趣但有时最好的解决方案来包装在宏中
#define INT_SIZEOF( x ) static_cast< int >( sizeof( (x) ) )
printf("[%.*s]", INT_SIZEOF(foo.field1), foo.field1);
Run Code Online (Sandbox Code Playgroud)
如果您的代码库对宏过敏,您可以为 做一个简单的语法包装static_cast,如下所示
int AsInt(size_t n) { return static_cast<int>( n ) }
printf("[%.*s]", AsInt(sizeof(foo.field1)), foo.field1);
Run Code Online (Sandbox Code Playgroud)
正如评论中所讨论的,该解决方案只能采用大小值,因此需要单独的sizeof运算符。sizeof另外,如果不返回适合整数的值,您将失去编译时错误检查的任何机会(尽管可能性很小)。
请注意,在这两种情况下,您的代码仍然很丑陋,但至少有一种更短,并通知读者正在发生一些丑陋的事情。
最后,另一个可能的不错的选择。
// constexpr is optional, you simply won't be able to use it in as many places if you don't use it
template<typename T> constexpr int intSizeof( T = T{} /*replace with () if necessary*/ )
{
return static_cast<int>( sizeof( T ) );
}
printf("[%.*s]", intSizeof<decltype(foo.field1)>(), foo.field1);
Run Code Online (Sandbox Code Playgroud)
这个解决方案绝对更 C++ 和更现代,而且没有实际成本
| 归档时间: |
|
| 查看次数: |
981 次 |
| 最近记录: |