- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道编译器是否会在32位和64位系统上使用不同的填充,因此我在一个简单的VS2019 C++控制台项目中编写了以下代码:
struct Z
{
char s;
__int64 i;
};
int main()
{
std::cout << sizeof(Z) <<"\n";
}
x86: 12
X64: 16
x86: 16
X64: 16
i
的字节存储在两个不同的字中。所以我认为编译器将以这种方式进行填充:
struct Z
{
char s;
char _pad[3];
__int64 i;
};
最佳答案
每个基本类型的大小和alignof()
(该类型的任何对象必须具有的最小对齐)是ABI 1设计选择,与体系结构的寄存器宽度分开。
与仅将每个struct成员对齐到其在结构内部的最小对齐方式相比,结构打包规则也可能更加复杂。这是ABI的另一部分。
面向32位x86的MSVC将__int64
的最小对齐方式设置为4,但的默认结构打包规则将结构内的类型相对于结构的开头对齐到min(8, sizeof(T))
。 (仅适用于非集合类型)。这不是直接引号,而是我对@ P.W答案中MSVC docs link的解释,基于MSVC实际执行的操作。 (我怀疑文本中的“较小者”应该在括号之外,但也许他们对编译指示和命令行选项上的交互有不同的看法?)
(包含char[8]
的8字节结构仍然只能在另一个结构中获得1字节对齐,或者包含alignas(16)
成员的结构仍可以在另一个结构中获得16字节对齐。)
请注意,ISO C++不保证基本类型具有alignof(T) == sizeof(T)
。 还请注意,MSVC的 alignof()
定义与ISO C++标准不匹配:MSVC表示alignof(__int64) == 8
,但是某些__int64
对象的对齐方式比该对齐方式少。
因此,令人惊讶的是,即使MSVC并不总是麻烦确保结构本身具有超过4字节的对齐方式,我们也会得到额外的填充,除非您在变量或struct成员上使用alignas()
进行指定以暗示对于类型。 (例如,函数内部堆栈上的本地struct Z tmp
仅具有4字节对齐,因为MSVC不会使用and esp, -8
这样的额外指令将堆栈指针向下舍入到8字节边界。)
但是, new
/malloc
在32位模式下确实为您提供了8字节对齐的内存,因此对于(通常是动态分配的对象)来说,这很有意义。强制将堆栈上的局部变量完全对齐会增加对齐堆栈指针的成本,但是通过将结构布局设置为利用8字节对齐的存储,我们可以获得静态和动态存储的优势。
这也可能旨在获取32位和64位代码,以在共享内存的某些结构布局上达成共识。 (但是请注意,x86-64的默认值为min(16, sizeof(T))
,因此,如果有任何16字节类型不是聚合(结构/联合/数组)并且没有alignas
。)
最小绝对对齐4来自32位代码可以假定的4字节堆栈对齐。 在静态存储中,编译器将为结构外部的var选择最多8或16个字节的自然对齐方式,以便使用SSE2 vector 进行有效复制。
在较大的功能中,出于性能方面的考虑,MSVC可能决定将堆栈对齐8。用于堆栈上的double
变量,实际上可以使用单个指令进行操作,或者也可以用于带有SSE2 vector 的int64_t
。请参阅此2006年文章中的“堆栈对齐”部分:Windows Data Alignment on IPF, x86, and x64。因此,在32位代码中,您不能依赖自然对齐的int64_t*
或double*
。
(我不确定MSVC是否会自行创建对齐程度更低的int64_t
或double
对象。如果您使用#pragma pack 1
或-Zp1
肯定可以,但这会更改ABI。但是除非您为int64_t
留出空间,否则可能不会。手动创建一个缓冲区并且不必费心去对齐它。但是假设alignof(int64_t)
仍然是8,那将是C++的未定义行为。)
如果使用alignas(8) int64_t tmp
,则MSVC会向and esp, -8
发出额外的指令。如果您不这样做,则MSVC不会做任何特殊的事情,因此tmp
是否以8字节对齐最终是幸运的。
其他设计也是可能的,例如i386 System V ABI(在大多数非Windows操作系统上使用)具有alignof(long long) = 4
但sizeof(long long) = 8
。这些选择
在结构之外(例如,堆栈上的全局var或局部变量),现代的32位编译器确实选择将int64_t
与8字节边界对齐以提高效率(因此可以使用MMX或SSE2 64位加载进行加载/复制)或x87 fild
进行int64_t->双重转换)。
这就是为什么现代版本的i386 System V ABI保持16字节堆栈对齐的原因之一:因此8字节和16字节对齐的本地变量是可能的。
在设计32位Windows ABI时,奔腾CPU至少即将出现。奔腾具有64位宽数据总线,因此,如果它是64位对齐的,它的FPU实际上可以在单个缓存访问中加载64位double
。
或对于fild
/fistp
,当从double
转换为/时,加载/存储一个64位整数。有趣的事实:由于奔腾:Why is integer assignment on a naturally aligned variable atomic on x86?,在x86上保证原子对齐的自然访问最多64位
脚注1 :ABI还包括一个调用约定,或者在MS Windows的情况下,可以选择各种调用约定,您可以使用 __fastcall
的函数属性来声明这些调用约定,但是原始类型(例如long long
)的大小和对齐要求编译器还必须达成共识,以使函数可以相互调用。 (ISO C++标准仅讨论单个“C++实现”; ABI标准是“C++实现”如何使其彼此兼容的方法。)
请注意,结构布局规则也是ABI 的一部分:编译器必须就结构布局达成共识,以创建可传递结构或结构指针的兼容二进制文件。否则,相对于单独编译的s.x = 10; foo(&x);
(可能在DLL中),foo()
相对于该结构的基数可能写入的偏移量与预期的不同。
脚注2 :
GCC也有C++ alignof()
错误,直到在为C11 _Alignof()
修复后一段时间才变成fixed in 2018 for g++8为止。请参阅该错误报告,以根据该标准的引用进行一些讨论,得出的结论是alignof(T)
应该确实报告您可以看到的最低保证对齐方式,而不是您想要的性能首选对齐方式。即使用比int64_t*
对齐方式少的alignof(int64_t)
是未定义的行为。
(通常在x86上可以正常工作,但是假设整个int64_t
迭代次数将达到16或32字节对齐边界的矢量化可能会出错。有关gcc的示例,请参见Why does unaligned access to mmap'ed memory sometimes segfault on AMD64?。)
gcc错误报告讨论了i386 System V ABI,它具有与MSVC不同的结构打包规则:基于最小对齐方式,不是首选。但是现代的i386 System V保持16字节的堆栈对齐,因此,仅在结构内部(由于ABI包含结构打包规则),编译器才能创建比自然对齐少的int64_t
和double
对象。无论如何,这就是为什么GCC错误报告将结构成员作为特殊情况进行讨论的原因。
与带有MSVC的32位Windows截然相反,在Windows中,结构打包规则与alignof(int64_t) == 8
兼容,但是除非您使用alignas()
专门要求对齐,否则堆栈上的本地变量始终可能未对齐。
32位MSVC具有奇怪的行为,即alignas(int64_t) int64_t tmp
与int64_t tmp;
不同,并发出额外的指令以对齐堆栈。这是因为alignas(int64_t)
类似于alignas(8)
,它比实际最小值更对齐。
void extfunc(int64_t *);
void foo_align8(void) {
alignas(int64_t) int64_t tmp;
extfunc(&tmp);
}
_tmp$ = -8 ; size = 8
void foo_align8(void) PROC ; foo_align8, COMDAT
push ebp
mov ebp, esp
and esp, -8 ; fffffff8H align the stack
sub esp, 8 ; and reserve 8 bytes
lea eax, DWORD PTR _tmp$[esp+8] ; get a pointer to those 8 bytes
push eax ; pass the pointer as an arg
call void extfunc(__int64 *) ; extfunc
add esp, 4
mov esp, ebp
pop ebp
ret 0
alignas()
或
alignas(4)
,我们将变得更加简单
_tmp$ = -8 ; size = 8
void foo_noalign(void) PROC ; foo_noalign, COMDAT
sub esp, 8 ; reserve 8 bytes
lea eax, DWORD PTR _tmp$[esp+8] ; "calculate" a pointer to it
push eax ; pass the pointer as a function arg
call void extfunc(__int64 *) ; extfunc
add esp, 12 ; 0000000cH
ret 0
push esp
而不是LEA/push;这是次要的优化遗漏。
int64_t*
的函数必须处理此潜在未对齐的指针,而无需获取有关其来源的任何信息。
alignof(int64_t)
确实为8,则该函数可能会在asm中以错误对齐指针的方式手写。或者可以用C编写,并在处理0或1个元素以达到对齐边界之后,使用SSE2内部函数(例如
_mm_load_si128()
)来要求16字节对齐。
int64_t
数组元素都按16对齐,因为它们都跨越8字节边界。
__int64
这样的特定于编译器的类型。您可以使用
int64_t
from <cstdint>
或
<stdint.h>
编写可移植代码。
int64_t
与
__int64
的类型相同。
long
或
long long
。
int64_t
保证完全为64位,没有填充,如果有的话,则为2的补码。 (这是所有针对正常CPU的明智的编译器。C99和C++要求
long long
至少为64位,在具有8位字节和2的幂的寄存器的机器上,
long long
通常恰好是64位,并且可以用作
int64_t
。或者,如果
long
是64位类型,则
<cstdint>
可能会将其用作typedef。)
__int64
和
long long
在MSVC中是相同的类型,但是MSVC无论如何都不执行严格的别名,因此它们是否是相同的类型并不重要,只是它们使用相同的表示形式。
关于c++ - 为什么 “alignment”在32位和64位系统上相同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55920103/
我试图找出在表格单元格上放置对齐属性与使用 text-align css 属性之间的区别。下面的代码显示了 IE 与其他浏览器中的不同结果。在 IE 中,对齐最终会对齐每个子子项,因此文本“test”
我正在 summernote HTML 编辑器上做一些 POC,我正在使用自定义工具栏,但我不知道如何添加对齐(左对齐、居中对齐、右对齐)工具栏,所以有人可以帮助我实现这一目标。 还有人可以帮我找到更
以下是从节对齐转换为文件对齐的步骤: 找到数据的 RVA 从 RVA 导出引用的数据所属的部分。这是微不足道的,因为部分不重叠。文件头中提供了各个部分的起始地址。 找出RVA和section的起始地址
align-self 在以下代码中, align-self 与 flex-wrap: nowrap 一起使用。 flex-container { display: flex; flex-wra
这是CSS: .divPhoto { border:1px solid #999; width:140px; height:140px; border-radius:3
我正在为 Windows Phone 8 开发,我已经设计了我的应用程序,我注意到有一个“分配网格”代码,默认情况下可以在新项目中取消注释。 看看下面的文件中的描述: --> 这是取
我们有浏览器前缀或黑客 (for Google and Safari) text-align: -webkit-right; (for Firefox) text-align:
最近我观察到,在 Clang 9.0 上 alignof 和 __alignof 为 unsigned long long 返回不同的值,并且在 https://reviews.llvm.org/D5
我已经一年多没有为 Android 开发了,我对它有点生疏了。我正在尝试设置一个有点简单的 UI:屏幕底部的底部栏和它上面的 fragment (但没有填充整个高度)。像这样: 我认为这会很简单,但经
你好,我正在尝试找到一种使用“讨厌的”align=center 技巧的方法.. 嗯,当我查看一些代码时,我注意到两个非常相似的片段呈现的并不相同。我找不到让他们表现相同的方法。这包括用 div 替换顶
抱歉这个愚蠢的问题。我只想知道我们什么时候讨论内存中的数据应该如何对齐之类的。这个主题是叫“内存对齐”还是“数据对齐”,还是我可以随便叫它什么? 最佳答案 在编程的上下文中,它被称为 data str
所以我只是想制作一个简单的导航栏,并且我刚开始使用 flexbox。为什么 align-content 在这里不起作用?我可以让 justify-content 工作,但我就是无法垂直对齐。这是代码。
我从这个 SO 开始答案,我试图使用提供的纯 flexbox 答案。 然而,当我尝试这个时,我看到了以下结果。 我不确定为什么 Button 4 在行中出现的位置高于其余元素。 HTML
我已通读 A complete guide to Grid ,但仍然对两组容器属性之间的差异感到困惑,即“justify/align-items”与“justify/align-content”。 我
我有一个simple plunker here. .container { display:flex; flex-flow: row nowrap; justify-content: sp
从 http://code.google.com/p/berkeleyaligner/ 下载主干代码后,我将该项目添加到 Eclipse 上的构建路径中。然后,使用下面的代码,我可以提取从 sourc
这个问题在这里已经有了答案: What's the difference between align-content and align-items? (15 个答案) 关闭 7 年前。 我发现 C
[short text][image1][image2]____________________________________ [this is a reallyyyyyyy............
我有一个很小的菜单列表,当鼠标靠近时它应该会增长。在其原始状态下,菜单是右对齐的,悬停时每第二个元素向右移动并左对齐以为增加的高度腾出空间(参见 JSFiddle )。 ul { font-siz
这个问题在这里已经有了答案: Align child elements of different blocks (3 个答案) 关闭 3 年前。
我是一名优秀的程序员,十分优秀!