使用指针的整数值检查指针对齐是否真的定义良好?

问题描述 投票:0回答:1

是否有一种有保证的(不是实现定义的!)方法来检查指针对齐?

查询指针对齐的最常见方法似乎是:

  1. 转换为整数
  2. 检查整数是否是对齐的倍数:
bool is_aligned(void const *ptr, size_t alignment) {
  return reinterpret_cast<intptr_t>(ptr) % alignment == 0;
}

例如,这就是 Boost.Align 检查对齐方式

但是,至少在 C++17 中,basic.compound#3.4 说:

指针类型的值表示是实现定义的。

此外,expr.reinterpret.cast#4 说:

指针可以显式转换为任何足够大以容纳它的整型。映射函数是实现定义的。

(例如)将指针表示为具有相反位顺序的整数似乎是合法的,在这种情况下,上面的简单算术将不起作用。

AFAICT,我们检查对齐的唯一有保证的方法是使用

std::align
,如果自由地阅读(我确信这是对
std::align
的滥用)可以像这样使用:

bool is_aligned(void const *ptr, size_t alignment) {
  void *mut_ptr = const_cast<void *>(ptr);
  size_t space = alignment;
  return std::align(alignment, alignment, mut_ptr, space) == ptr;
}

然而,在绝大多数平台上,指针只是奇特的整数,或者我希望 Boost 有一个代码路径。是否有任何平台(除了 ds9k :P)其中指针不是只是奇特的整数?

通过标准化“

reinterpret_cast<intptr_t>(ptr)
应具有与
ptr
相同的对象表示”或“如果
reinterpret_cast<intptr_t>(ptr) % alignment == 0
ptr
对齐”,我们会失去什么?似乎这些都不会排除分段内存或具有陷阱表示的指针,这是我能想到的两种非典型情况。
如果不出意外的话,有没有理由不标准化

alignment

编辑:

我的具体非玩具用例是我有std::is_aligned()。我对

std::byte const *ptr;
的唯一了解是它包含 1024 个
ptr
的对象表示。如何检查
int
reinterpret_cast
或使用
ptr
是否安全?
    

c++ c++17 undefined-behavior
1个回答
0
投票
(例如)将指针表示为具有相反位顺序的整数似乎是合法的,在这种情况下,上面的简单算术将不起作用。

是的,没有什么禁止这样做。也有可能不存在足够大的整数类型来表示所有指针值,在这种情况下
assume_aligned

不应该可用。


AFAICT 我们检查对齐的唯一有保证的方法是使用 std::align,如果自由地阅读(我确信这是对 std::align 的滥用)可以像这样使用:

如果输入指针指向的存储空间不是连续的至少
intptr_t

长,则该函数具有未定义的行为。所以尺寸参数可能应该是

alignment
。我在规范中没有看到任何要求对齐大于尺寸的内容。
无论如何,

1

的规范对我来说似乎都被破坏了,所以不确定这是否有效。它无法指定结果指针指向哪个对象,假装可以有一个仅指向存储的指针,并且它还忽略了

std::align
有意施加的可达性条件。


如果不出意外,是否有理由不标准化 std::is_aligned()?

据我所知,情况并非如此。
std::launder

似乎已经具有上面讨论的功能。一个用户友好的包装器很容易做到。

    

© www.soinside.com 2019 - 2024. All rights reserved.