【问题标题】:Check input buffer alignment in C++/C++11: what is the best way?检查 C++/C++11 中的输入缓冲区对齐:最好的方法是什么?
【发布时间】:2018-03-20 04:42:29
【问题描述】:

我知道 C++11 提供了 alignofalignasalign,但在这种情况下,我想检查一个已经分配的输入缓冲区。

我也知道 C 提供了 uintptr_t 来精确匹配指针类型以转换为整数(然后检查对齐很容易),但这种数据类型是 not guaranteed to be there in C++/C++11

对于 C 的问题已回答 here。在这种情况下,似乎可以转换为任何整数,但在 C++ 中,我收到“丢失精度”警告。

所以,现在我查看Converting a pointer into an integer,但在那里我发现uintptr_t 的大量使用,但不能保证在那里。

那么,在 C++/C++11 中检查输入指针是否对齐的最佳方法是什么?

(注意:经过所有这些研究和推理,我想出了一个解决方案,但我期待其他建议!)

【问题讨论】:

  • 从 64 位指针转换为 int 时会丢失精度。使用 long long int。
  • @YvesDaoust:在 cmets 部分写答案(或部分答案)时,同行评审功能丢失。使用答案部分,或将答案留给其他人。不,不要只是随机猜测类型宽度 - 使用正确的类型来完成工作.....看到了吗?我不能拒绝您的评论以表示它对其他访问者不正确:(。

标签: c++ c++11


【解决方案1】:

uintptr_t 是检查指针内数值的正确类型。如果不存在,则意味着没有足够大的整数类型来容纳整个指针。

但是,对齐只影响低位,因此实际上没有必要存储整个值。 size_t 应该始终适合捕获与对齐相关的位。 (特别是 alignof 的结果类型,如果不够,语言自身的对齐逻辑就会中断)

来自标准部分[basic.align]

对齐表示为 std::size_t 类型的值。有效对齐仅包括由基本类型的alignof 表达式返回的值以及附加的实现定义的值集,这些值可能为空。每个对齐值应为 2 的非负整数幂。

【讨论】:

  • uintmax_t 怎么可能不够大到不能旧指针的数值?此外,我看不到后果“如果uintptr_t 不存在,那么就没有足够大的整数类型来容纳整个指针”:这不是标准所说的定义或不定义uintptr_t 的规则(它是只是可选的)。
  • 另外,你的建议(通过size_t)并声明“无论如何我们需要最低有效字节”不适合在一起,因为如果你使用太小的类型,你会得到一个“失去精度”警告。那么,既然我们需要最低有效字节,您将如何进行转换,例如从void *uint8_t? (因为无论如何我们都需要最低有效位)
  • @Antonio: reinterpret_cast<size_t>(pointer_to_test) 并且可能需要在本地禁用警告。此外,如果整数缩小的警告说“失去精度”这是一个编译器错误,它应该说“失去范围”。
  • 不同的编译器输出(使用unsigned intsize_t 恰好足够大):Clangloses informationg++loses precision。 Visual Studio:warning C4311: 'reinterpret_cast': pointer truncationwarning C4302: 'reinterpret_cast': truncation。在多平台项目中很难保持沉默。
  • @Antonio:我很乐意为您提交给编译器供应商的错误报告投票。 size_t 是根据 C++ 标准存储对齐信息的正确类型。我会添加引用。
【解决方案2】:

这是我现在使用uintmax_t的解决方案

#include <cstdint>

template<typename T>
bool isAlignedAs(void* in) {
  return !(reinterpret_cast<uintmax_t> (in) % alignof(T));
}

测试here


要确认 100% 不会产生丢失精度警告,可以在代码的任何位置添加断言:

static_assert(sizeof (uintmax_t) >= sizeof (void *) ,
              "No suitable integer type for conversion from pointer type");

【讨论】:

  • uintmax_t 不必要地大并且可能非常慢(考虑当今 CPU 上的 256 位整数 - 进位等需要通过软件仿真来执行)
  • @BenVoigt 毫无疑问,编译器会优化转换操作(实际上可能没有操作)。这不是一个令人担忧的问题。
猜你喜欢
  • 2023-03-20
  • 2015-03-19
  • 2020-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 1970-01-01
相关资源
最近更新 更多