是否有一种可移植的(C++ 标准)方法来计算先前对齐的指针?

Vai*_*Man 9 c++ pointers

给定[ , ] 之间的alignas(N) char buffer[N];and ,我可以使用and获得指向的指针吗?char* p&buffer[0]&buffer[N-1]buffer[0]pN

char* previous_aligned_pointer(char* ptr, size_t align) {
   // how?
}

int main() {
  constexpr int N = 32;
  alignas(N) char buffer[N];
  assert(previous_aligned_pointer(&buffer[rand() % N], N) == &buffer[0]);
}
Run Code Online (Sandbox Code Playgroud)

我想用可移植的 C++ 来完成它(如果可能的话),因此uintptr_t可能不会使用诸如将指针转换为指针然后对其执行算术之类的操作。

eer*_*ika 5

有一个标准库函数可以获取一个对齐的指针。它被称为std::align. 然后您可以减去对齐方式以获得前一个对齐方式。

一般来说,这可能会在缓冲区之外进行指针算术,在这种情况下,减法在技术上将是 UB。如果这是一个问题,那么如果您可以在缓冲区中分配额外的空间,以便下一个对齐的指针始终位于缓冲区内,那么您可以避免使用 UB。

唯一的其他方法是自己实现它,这必须依赖于整数类型的转换,而整数类型依赖于实现相关的无保证行为。结论:不,我认为不存在一个通用的严格符合标准的解决方案。


但是,对于您的示例情况,没有问题。下一个对齐的地址是超出末尾的指针,因此可以减去 N 以获得缓冲区开头的地址。

  • 在这种特殊情况下,“std::align”产生的指针将指向缓冲区的末尾。这仍然是一个有效的(尽管不可取消引用)指针。 (2认同)