警告:算术中使用的“void *”类型指针

Posted

技术标签:

【中文标题】警告:算术中使用的“void *”类型指针【英文标题】:warning: pointer of type ‘void *’ used in arithmetic 【发布时间】:2015-01-01 13:16:02 【问题描述】:

我正在从内存映射中写入和读取寄存器,如下所示:

//READ
return *((volatile uint32_t *) ( map + offset ));

//WRITE
*((volatile uint32_t *) ( map + offset )) = value;

但是编译器给了我这样的警告:

warning: pointer of type ‘void *’ used in arithmetic [-Wpointer-arith]

如何更改代码以删除警告?我正在使用 C++ 和 Linux。

【问题讨论】:

转换为 char* - 假设你想要 byte 偏移量。你呢? 是的,地图是无效的*,谢谢。 您需要将map 转换为指向大小为1 的类型的指针。标准保证大小为1 的唯一类型是char,因此您需要将其转换为@ 987654326@. @barakmanos: char 和变体(signed charunsigned char),所以这是一个惊人的 3 种尺寸 1 【参考方案1】:

由于void* 是一个指向未知类型的指针,因此您无法对其进行指针运算,因为编译器不知道所指向的对象有多大。

最好的办法是将map 转换为一个字节宽的类型,然后进行算术运算。您可以为此使用uint8_t

//READ
return *((volatile uint32_t *) ( ((uint8_t*)map) + offset ));

//WRITE
*((volatile uint32_t *) ( ((uint8_t*)map)+ offset )) = value;

【讨论】:

但是 void * 是一个众所周知的类型,它是一个地址类型,它可以指向任何地址类型...我想解决方案是静态转换为 uintptr_t *,然后 转换为char 会更惯用,因为sizeof(char) 被定义为1。 @Artyer uint8_t 更受欢迎,并且保证大小为 1 字节。 @VictorPolevoy 只有uint_least8_t 保证大小为1 字节,因为uint8_t 不保证存在(我知道这在实践中永远不会发生,但仍然如此)。另外,uint8_t 表示“8 位数字”,char 表示“字节”,offset 是字节偏移量。 @Artyer 呃,我从来不知道uint_least8_t,谢谢。但是我一直认为char 是一个“字符”,而uint8_t 是一个“字节”,我一直都错了吗? :) 另外,从 Rust 回到 C++ 听起来很奇怪,uint8_t 不能保证存在 :)【参考方案2】:

类型 void 是不完整类型。它的大小是未知的。所以带有指向 void 的指针的指针算术没有意义。您必须将类型为 void 的指针转换为其他类型的指针,例如指向 char 的指针。 还要考虑到您不能分配使用限定符 volatile 声明的对象。

【讨论】:

【参考方案3】:

如果对 void 指针使用算术确实是您想要的,因为 GCC 可以实现(请参阅 Arithmetic on void- and Function-Pointers),您可以使用 -Wno-pointer-arith 来抑制警告。

【讨论】:

以上是关于警告:算术中使用的“void *”类型指针的主要内容,如果未能解决你的问题,请参考以下文章

C++ 指针警告:算术溢出:对 4 字节值使用运算符“-”,然后将结果转换为 8 字节值

C++指针的算术运算 关系运算

void类型及void指针

ISO C Void * 和函数指针

C语言指针用法详解 指针的算术运算

使用的类型 va_list (aka_builtin_va_list) 在 BWDB.m 文件中需要算术或指针类型