C++ 内存地址的数字表示和对齐之间的关系?
例如:C++ 内存地址的数字表示和对齐之间的关系?,c++,pointers,memory,memory-alignment,C++,Pointers,Memory,Memory Alignment,例如: std::ptrdiff_t dist(void* a, void* b) { return static_cast<std::uint8_t*>(b) - static_cast<std::uint8_t*>(a); } Align8Type align8; // alignof(Align8Type) == 8 std::uintptr_t(&align8) & 3; // [1] dist(nullptr, &align8)
std::ptrdiff_t dist(void* a, void* b)
{
return static_cast<std::uint8_t*>(b) - static_cast<std::uint8_t*>(a);
}
Align8Type align8; // alignof(Align8Type) == 8
std::uintptr_t(&align8) & 3; // [1]
dist(nullptr, &align8) & 3; // [2]
Align8Type* p = reinterpret_cast<Align8Type*>(static_cast<std::uint8_t*>(nullptr) + dist(nullptr, &align8));
assert(&align8 == p); // [3]
std::ptrdiff\t dist(void*a,void*b)
{
返回静态强制转换(b)-静态强制转换(a);
}
align8键入align8;//alignof(Align8Type)==8
std::uintpttr_t(&align8)&3;//[1]
距离(nullptr,&align8)&3;//[2]
Align8Type*p=重新解释强制转换(静态强制转换(nullptr)+距离(nullptr和align8));
断言(&align8==p);//[3]
<强> >代码> STD::UIT88T T <代码>支持< /强>,结果是[1 ]和[2 ]保证为0,并且(3)保证在C++标准中是真的吗? 如果不是,那么在实践中呢?
< P>在C++标准中, 声明为字符(char)的对象应足够大,以便存储 实现的基本字符集的任何成员 < > C++内存模型中的基本存储单元是字节。A. 字节至少足够大,可以包含基本 执行字符集(2.3)和 Unicode UTF-8编码形式,由连续序列组成 位数,位数由实现定义 每个字节都有一个唯一的地址 一个uint_8
不一定是一个字节。一个字节不一定是8位
是否保证[1]和[2]的结果为0?
假设Align8Type的地址为8字节对齐:
[1] 是:根据前面假设的定义
[2] 是的,即使字节大小可能大于uint_8,假设Align8Type有一个地址8字节对齐,地址也将是8的倍数。(uint_8小于或等于一个字节)
<>强> >(3)在C++标准中是否成立?< /强> < /P>
否:dist
返回两个指针之间的uint_8
距离,而不是地址距离
编辑:
编辑以回答重新定义的问题。本标准不保证指针的表示形式[注1]。指针的值不一定直接映射到连续整数,指向不同对齐类型的指针也不一定具有相同的表示形式。因此,以下任何一项都是可能的:
Align8Type
鉴于上述情况,我的解释是:
std::uintptr\u t(&align8)&3==0
错。即使Align8Type
是可定义的,也不能保证Align8Type*
到std::uintptr\u t
的转换是可被8整除的数字。例如,在32位字寻址机器上,底层硬件地址mod 8可以是0、2、4或6
dist(nullptr和align8)&3==0
错。从指向对象的指针中减去nullptr
是未定义的行为。(§5.7/5:“除非两个指针都指向同一数组对象的元素,或者一个指针超过数组对象的最后一个元素,否则行为是未定义的。”)
重新解释强制转换(静态强制转换(nullptr)+dist(nullptr和align8))==&align8
错。首先,根据2,dist
的调用是未定义的行为。其次,将该值添加到空指针是未定义的行为
只要T2
的校准要求低于T1
(§5.2.10/7),就可以保证T1*
到T2*
再回到T1*
的往返转换。在这种情况下,T1
是Align8Type
,T2
是uint8\u t
,并且对齐限制可能成立,因此如果不是因为算术的未定义行为,这将起作用。也就是说,您可以将&align8
强制转换为uint8*
,然后将其强制转换回Align8Type
。您甚至可以将整数0
添加到中间uint8\u t*
指针,但不能添加其他整数
这些身份在实践中有效吗?他们可能在C++实现上工作在8位字节寻址的2补码机上,这是非常常见的(比上面提到的理论动物更常见,在统计学上,与独角兽一样常见)。但从技术上讲,它们使您的代码不可移植。我不知道积极的优化会对第2点和第3点中提到的UB做什么,所以我不建议在生产代码中冒险
笔记: