【问题标题】:Void Pointer Arithmetic in C++11 [closed]C ++ 11中的空指针算术[关闭]
【发布时间】:2016-04-20 14:48:27
【问题描述】:

我真的很想使用一些 void 强制转换来保存二进制数据,但这要么是 g++ 警告级联,要么是 lot 的强制转换。在 C++(最好是 c++11 或更高版本)中是否有一种简单且安全的方法来执行 void 指针算术?

我只在带有 gnu 编译器的 posix 系统上工作,所以这里没有问题。

用例:

  • 我有 void * ptr 到大小 > 1GB 的数据。

  • 我还有其他功能要做,我们称它为 stuff() 它是外部库的一部分并获取 (void *, size_t) 作为参数。

  • stuff(ptr, n) 可能会改变底层内存。基本上我需要通过 ptr* 的切片。

代码假设,是,我猜,不会是可移植的。

如果我无法找到更优雅的解决方案,我想我会选择 -Wno-pointer-arithmetics,但答案中提出的解决方案有所帮助

【问题讨论】:

  • 您不能对 void 指针进行指针运算。安全与否,这是不可能的。
  • 不。算术不适用于void 指针。您可以尝试的解决方案取决于您未显示的代码。
  • 为什么将“二进制数据”存储为void 而不是字节(即uint8_t)?
  • @KeithThompson:不能说我曾经遇到过这样的系统。就我个人而言,我宁愿使用uint8_t,因为它清楚地表明它不是字符数据,并明确指出我们需要 8 位字节。

标签: c++ c++11 pointer-arithmetic


【解决方案1】:

取决于您在询问算术时的想法。以下代码非常好,可以由 GNU g++ -std=c++11 编译:

#include <cstdlib>
#include <cstdio>

int main()
{
    void * x = std::malloc(100);
    std::printf("%p\n", x);
    std::printf("%p\n", x+20);
    return 0;
 }

(编辑2) 问题很令人困惑,但如果 gnu 编译器可以处理,那么 void 指针算术是完全可以的。 GNU 基本上将 void * 定义为以一个字节为增量的指针,因此上述代码中的所有语句都是正确的。我没有用其他编译器测试过,就这个问题考虑,我不必。

对于 GNU 以外的编译器,使用无符号整数类型非常安全和正确:首先将指针转换为 1byte 整数类型之一:

  • size_t
  • uintptr_t / intptr_t
  • 或者如果您知道内存大小和型号 - 精确的固定宽度整数}

如果内存寻址将更改为每个单元的任何其他奇怪大小 - 您需要使用在地址添加 +1 后将指向下一个物理存储单元的类型。

还要澄清一下 = bool 不是 1bit 类型...它的填充(别名)char 里面有一些包装魔法。

【讨论】:

  • 指针算法适用于元素类型。你如何获得第 20 个void?操作只是没有意义。如果它有任何作用,我相信它是编译器的增强,而不是标准的一部分。
  • (对不起,我忍不住了)
  • 马克是对的,void 指针上的算术是a GCC extension,但没有标准。
  • void 没有大小,将值添加到指针(例如pointer + n)获取第 n 个元素的值。通过移动到地址 - pointer address + n * (size of element) 到达第 n 个元素。没有void 的大小,没有void 指针的算术运算。
  • "在 c++11 之前 void 是不完整的类型,因此 void 不能被称为 sizeof() "——我不相信 C++11 改变了任何内容那个区域。如果您声称 C++11 标准使 sizeof (void) 有效,请引用进行该更改的标准部分。
猜你喜欢
  • 2010-09-28
  • 2015-03-05
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 2012-07-27
  • 2021-02-15
相关资源
最近更新 更多