rxu*_*rxu 5 c++ bit-manipulation memory-alignment
根据我对维基百科的理解,我可以通过以下按位运算找到具有正确对齐方式的下一个最接近元素的索引。
Assuming the address of the 1st element has the correct alignment.
Assuming the index_alignment is a power of 2.
new_index = (current_index + index_alignment - 1) & ~(index_alignment - 1).
new_address = address_of_1st_element + new_index
index_alignment is 16 bytes/sizeof(type of element) for SSE.
Run Code Online (Sandbox Code Playgroud)
是否可以直接在地址上使用它来从任何给定地址找到下一个最接近的对齐地址?(这样比较快吗?)
为了快速做到这一点,我正在考虑以下事项。
new_address = (current_address + alignment - 1) & ~(alignment -1)
alignment here is 16 for SSE.
Run Code Online (Sandbox Code Playgroud)
当我实现这个时,我发现以下代码无法编译...
根据 Salva 和 Rotem 的建议修复了代码
#include <iostream>
#include <stdint.h>
#define ALIGNMENT 16
using namespace std;
uint32_t* fix_ptr(uint32_t* ptr){
return (uint32_t*)(
(uintptr_t(ptr) + uintptr_t(ALIGNMENT) - 1)
&~ uintptr_t(ALIGNMENT - 1)
);
}
void print_ptr (uint32_t* ptr){
cout << (long long)(void*)ptr << endl;
}
void test(uintptr_t ptr_as_int){
uint32_t* ptr1 = (uint32_t*) ptr_as_int;
cout << "Initial address: ";
print_ptr(ptr1);
uintptr_t alignment = ALIGNMENT;
cout << " alignment: " << alignment << endl;
cout << " alignment - 1: " << (alignment - 1) << endl;
cout << " alignment & alignment: " << (alignment & alignment) << endl;
uint32_t* ptr_fixed = fix_ptr(ptr1);
cout << " fixed address: ";
print_ptr(ptr_fixed);
}
int main(void){
test(1000);
test(16);
}
Run Code Online (Sandbox Code Playgroud)
输出(用g++ code.cpp编译)
Initial address: 1000
alignment: 16
alignment - 1: 15
alignment & alignment: 16
fixed address: 1008
Initial address: 16
alignment: 16
alignment - 1: 15
alignment & alignment: 16
fixed address: 16
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,1000 变为 1008,16 变为 16。可能适合我目前的使用。不知道有没有更快的方法。
谢谢。
从 C++11 开始,C++ 标准库std::align在标头中就有执行此操作的函数。memory至少在GNU 实现(libstdc++) std::align中,它的位操作与 OP 几乎相同:
const auto __aligned = (__intptr - 1u + __align) & -__align;
除了第一个位置之外的唯一区别-1是,它不是~(__align - 1)使用-__align,因为两者是等效的。
std::align还接受一个size和一个space参数,并检查正确对齐后给定类型是否仍然适合给定的缓冲区/分配space,以及从space参数(引用)中减去用于对齐的字节。
以下是没有这些检查和仅检查所需的附加参数的版本。
#include <cstddef>
#include <cstdint>
inline void *align(std::size_t alignment, void *ptr) noexcept {
const auto intptr = reinterpret_cast<std::uintptr_t>(ptr);
const auto aligned = (intptr - 1u + alignment) & -alignment;
return reinterpret_cast<void *>(aligned);
}
Run Code Online (Sandbox Code Playgroud)