有没有更好的方法来缓解这个警告?
Are there better ways to ease this warning?
我有一个结构,我在其中使用位域来优化内存。我有一个 uint64_t
类型,我想打印它的值。编译时它向我显示此警告:format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘long unsigned int:48’ [-Wformat=]
我已经尝试通过在编译时键入来抑制此警告 -Wno-format
。我想知道是否有更好的方法来做到这一点。
这里是一些代码:
#include <stdint.h>
#include <stdio.h>
typedef struct gn_addr
{
unsigned int m:1;
unsigned int st:5;
unsigned int reserved:10;
uint64_t mid:48;
} gn_addr ;
void gn_addr__print(gn_addr *self)
{
printf("M=>%d\nST=>%d\nReserved=>%d\nMID=>%lu\nTotal size %ld bytes\n",
self->m, self->st, self->reserved, self->mid, sizeof(self));
}
首先,对 uint64_t
和 size_t
类型使用正确的格式说明符,使用 PRIu64
宏,如 inttypes.h
和 %zu
中所定义。
也就是说,对于位域变量,
- 你可以使用强制转换,比如
(uint64_t)self->mid
或者你可以使用uint64_t
类型的中间变量,将成员变量值赋给新的中间变量,并将其作为相应的参数传递给printf()
格式说明符,如
uint64_t temp = self->mid;
printf("%"PRIu64 "\n", temp);
虽然您绝对应该应用其他答案中的修复程序以获得可移植格式说明符,但警告仍然存在。原因是像 printf
这样的可变参数函数的额外参数会进行参数提升。参数提升包括整数提升。
整数提升规则会将任何转换等级小于 int
/unsigned
的整数以及位域转换为 int
/unsigned
。因此,对于您的初始位字段,您会自动获得 int
。
对于转换等级高于 int
/unsigned
的整数,不会发生提升。因此,您的位域不会提升为 uint64_t
,并且您会收到有关参数不匹配的警告。你需要一个演员。
(uint64_t)self->mid
顺便说一句,由于没有人提到,size_t
(sizeof
运算符的类型)的可移植格式说明符是 %zu
。您应该使用它而不是 %ld
.
像printf
这样的函数正在被编译器检查(不是全部)。编译器检查格式说明符是否与传递的参数类型匹配。您需要进行显式转换才能使 Warning
消失。正如其他答案中提到的,有一些隐式整数提升规则,您需要了解它们(感谢@storyTeller)。
The rules for integer promotions will convert any integer with a conversion rank less than int/unsigned,as well as bit-fields, into the an int/unsigned. So for your initial bit-fields, you get unsigned int automatically.
For integers with a higher conversion rank than int/unsigned, no promotion occurs. So your bit-field is not promoted to an uint64_t, and you get a warning about argument mismatch. You need a cast.
试试这个:
(uint64_t)self->mid
I have already tried to supress this warning by typing while compiling -Wno-format. I'm wondering if there are a better way to do it.
隐藏您的警告不是一个好主意。它们的产生是有原因的。我建议使用 -Wall
、-Wshadow
、-Wextra
等警告标志和其他重要标志。他们可以帮助您部署代码,减少错误数量。
关于您的假设:
I have a struct where I use bitfields to optimize memory.
我想指出,您的带位域的结构不会像您考虑的那样优化内存。有一个叫做 Padding
和 Data Alignment
的东西可以帮助你进一步减少内存占用。
检查此 question。
我有一个结构,我在其中使用位域来优化内存。我有一个 uint64_t
类型,我想打印它的值。编译时它向我显示此警告:format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 5 has type ‘long unsigned int:48’ [-Wformat=]
我已经尝试通过在编译时键入来抑制此警告 -Wno-format
。我想知道是否有更好的方法来做到这一点。
这里是一些代码:
#include <stdint.h>
#include <stdio.h>
typedef struct gn_addr
{
unsigned int m:1;
unsigned int st:5;
unsigned int reserved:10;
uint64_t mid:48;
} gn_addr ;
void gn_addr__print(gn_addr *self)
{
printf("M=>%d\nST=>%d\nReserved=>%d\nMID=>%lu\nTotal size %ld bytes\n",
self->m, self->st, self->reserved, self->mid, sizeof(self));
}
首先,对 uint64_t
和 size_t
类型使用正确的格式说明符,使用 PRIu64
宏,如 inttypes.h
和 %zu
中所定义。
也就是说,对于位域变量,
- 你可以使用强制转换,比如
(uint64_t)self->mid
或者你可以使用
uint64_t
类型的中间变量,将成员变量值赋给新的中间变量,并将其作为相应的参数传递给printf()
格式说明符,如uint64_t temp = self->mid; printf("%"PRIu64 "\n", temp);
虽然您绝对应该应用其他答案中的修复程序以获得可移植格式说明符,但警告仍然存在。原因是像 printf
这样的可变参数函数的额外参数会进行参数提升。参数提升包括整数提升。
整数提升规则会将任何转换等级小于 int
/unsigned
的整数以及位域转换为 int
/unsigned
。因此,对于您的初始位字段,您会自动获得 int
。
对于转换等级高于 int
/unsigned
的整数,不会发生提升。因此,您的位域不会提升为 uint64_t
,并且您会收到有关参数不匹配的警告。你需要一个演员。
(uint64_t)self->mid
顺便说一句,由于没有人提到,size_t
(sizeof
运算符的类型)的可移植格式说明符是 %zu
。您应该使用它而不是 %ld
.
像printf
这样的函数正在被编译器检查(不是全部)。编译器检查格式说明符是否与传递的参数类型匹配。您需要进行显式转换才能使 Warning
消失。正如其他答案中提到的,有一些隐式整数提升规则,您需要了解它们(感谢@storyTeller)。
The rules for integer promotions will convert any integer with a conversion rank less than int/unsigned,as well as bit-fields, into the an int/unsigned. So for your initial bit-fields, you get unsigned int automatically.
For integers with a higher conversion rank than int/unsigned, no promotion occurs. So your bit-field is not promoted to an uint64_t, and you get a warning about argument mismatch. You need a cast.
试试这个:
(uint64_t)self->mid
I have already tried to supress this warning by typing while compiling -Wno-format. I'm wondering if there are a better way to do it.
隐藏您的警告不是一个好主意。它们的产生是有原因的。我建议使用 -Wall
、-Wshadow
、-Wextra
等警告标志和其他重要标志。他们可以帮助您部署代码,减少错误数量。
关于您的假设:
I have a struct where I use bitfields to optimize memory.
我想指出,您的带位域的结构不会像您考虑的那样优化内存。有一个叫做 Padding
和 Data Alignment
的东西可以帮助你进一步减少内存占用。
检查此 question。