作为构建.NET的标准,CLI Spec(ECMA-335)针对基元类型的对齐规则具有如下的描述。按照这个标准,我们是这么理解的:8字节的数据类型(int64、unsigned int64和float64)根据采用的机器指令架构选择4字节或者8字节对其。进一步来说,它们在x86/x64机器上的对其字节分别为4字节和8字节。

Built-in data types shall be properly aligned, which is defined as follows:

  • 1-byte, 2-byte, and 4-byte data is properly aligned when it is stored at a 1-byte, 2-byte, or 4-byte boundary, respectively.

  • 8-byte data is properly aligned when it is stored on the same boundary required by the underlying hardware for atomic access to a native int.

Thus, int16 and unsigned int16 start on even address; int32, unsigned int32, and float32 start on an address divisible by 4; and int64, unsigned int64, and float64 start on an address divisible by 4 or 8, depending upon the target architecture. The native size types (native int, native unsigned int, and &) are always naturally aligned (4 bytes or 8 bytes, depending on the architecture). When generated externally, these should also be aligned to their natural size, although portable code can use 8-byte alignment to guarantee architecture independence. It is strongly recommended that float64 be aligned on an 8-byte boundary, even when the size of native int is 32 bits.

我们通过一个简单控制台程序来验证这个说法。为了在64位机器上模拟32位平台,我们按照如下的方式修改了.cspro文件,将PlatformTarget属性设置为x86(默认为Any CPU)。

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
</Project>

在演示程序中,我们定义了如下一个名为Foobar的结构体Record。该结构体具有两个字段,类型分别为byte和ulong(unsigned int64)。我们将这两个字段分别设置为byte.Max(FF)和ulong.MaxValue(FF-FF-FF-FF-FF-FF-FF-FF-FF),并将在内存中的二进制形式输出来。为了进一步确定当前的环境与CLI Spec的描述一致,我们将Environment.Is64BitProcess属性(确定是不是64位处理器),ulong类型的字节数(确定这是一个”8-byte data”)和IntPtr.Size(确定native int类型的对其边界是4字节)。

unsafe
{
var bytes = new byte[sizeof(Foobar)];
var foobar = new Foobar(byte.MaxValue, ulong.MaxValue);
Marshal.Copy(new nint(Unsafe.AsPointer(ref foobar)), bytes, 0, bytes.Length);
Console.WriteLine(BitConverter.ToString(bytes));
Console.WriteLine($"Environment.Is64BitProcess = {Environment.Is64BitProcess}");
Console.WriteLine($"sizeof(ulong) = {sizeof(ulong)}");
Console.WriteLine($"IntPtr.Size = {IntPtr.Size}");
} public record struct Foobar(byte Foo, ulong Bar);

从如下的输出可以看出,当前的环境与CLI Spec描述的32位处理器架构是一致的,但是ulong类型的字段Bar采用的对其长度是8字节而不是4字节(如果采用4字节对其的话,二进制形式应该FF-00-00-00-FF-FF-FF-FF-FF-FF-FF-FF-FF)。

对于这个问题,我们目前尚未找到一个权威的答案,莫不是我对CLI Spec的解读有误?还是我们的验证程序有问题?希望对此熟悉的朋友不吝赐教!我们目前Google如下这些相关的说法:

Memory alignment on a 32-bit Intel processor

The usual rule of thumb (straight from Intels and AMD's optimization manuals) is that every data type should be aligned by its own size. An int32 should be aligned on a 32-bit boundary, an int64 on a 64-bit boundary, and so on. A char will fit just fine anywhere.

Another rule of thumb is, of course "the compiler has been told about alignment requirements". You don't need to worry about it because the compiler knows to add the right padding and offsets to allow efficient access to data.

WHY IS THE DEFAULT ALIGNMENT FOR `INT64_T` 8 BYTE ON 32 BIT X86 ARCHITECTURE?

Interesting point: If you only ever load it as two halves into 32bit GP registers, then 4B alignment means those operations will happen with their natural alignment.

However, it's probably best if both halves of the variable are in the same cache line, since almost all accesses will read / write both halves. Aligning to the natural alignment of the whole thing takes care of that, even ignoring the other reasons below.

32bit x86 can load 64bit integers in a single 64bit-load using MMX or SSE2 movq. Handling 64bit add/sub/shift/ and bitwise booleans using vector instructions is more efficient (single instruction), as long as you don't need immediate constants or mul or div. The vector instructions with 64b elements are still available in 32b mode.

Atomic 64bit compare-and-exchange is also available in 32bit mode (lock CMPXCHG8B m64 works just like 64bit mode's lock CMPXCHG16B m128, using two implicit registers (edx:eax)). IDK what kind of penalty it has for crossing a cache-line boundary.

Modern x86 CPUs have essentially no penalty for misaligned loads/stores unless they cross cache-line boundaries, which is why I'm only saying that, and not saying that misaligned 64b would be bad in general. See the links in the x86 wiki, esp. Agner Fog's guides.

Why is the "alignment" the same on 32-bit and 64-bit systems?

MSVC targeting 32-bit x86 gives __int64 a minimum alignment of 4, but its default struct-packing rules align types within structs to min(8, sizeof(T)) relative to the start of the struct. (For non-aggregate types only). That's not a direct quote, that's my paraphrase of the MSVC docs link from @P.W's answer, based on what MSVC seems to actually do. (I suspect the "whichever is less" in the text is supposed to be outside the parens, but maybe they're making a different point about the interaction on the pragma and the command-line option?)

Int64针对32位架构是按照4字节还是8字节对齐?的更多相关文章

  1. 32位系统和x86的关系?

    32位操作系统针对32位CPU设计,cpu的位是指一次性可处理的数据量是多少,也等于寻址空间的大小或是通用寄存器的大小,一般数据总线的宽度也和cpu位数相同,但也有例外(如8088数据总线宽度为8然而 ...

  2. 32位嵌入式微处理器(processor)一览

    32位嵌入式微处理器(processor)一览 由于嵌入式系统的专用型与定制性,与全球PC市场不同,没有一种微处理器或者微处理器公司可以主导嵌入式系统.本文分析了当前市场上主流的一些32位嵌入式微处理 ...

  3. Xubuntu 计划从 19.04 版本开始停止提供 32 位安装镜像(XDE/LXQt的 Lubuntu 成为了目前唯一仍然提供 32 位安装镜像的 Ubuntu 桌面发行版)

    Ubuntu 17.10 以及其他许多 *buntu 衍生品都已在今年早些时候停止提供 32 位安装镜像.但其中有一个依然坚持提供适用于 i386 架构的镜像,它就是 Xubuntu,但现在 Xubu ...

  4. iOS-程序发布-32位和64位系统的兼容

    在苹果推出iPhone5S时,64位的应用就走到了眼前.当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位. 我记得自己刚刚接触电脑时还有16位的系统,指针 ...

  5. iOS上应用如何兼容32位系统和64位系统

    在苹果推出iPhone5S时,64位的应用就走到了眼前.当时就看见苹果官方资料宣布iOS7.x的SDK支持了64位的应用,而且内置的应用都已经是64位. 我记得自己刚刚接触电脑时还有16位的系统,指针 ...

  6. iOS如何兼容的应用程序32位系统和64Bit系统

    苹果发布iPhone5S时刻,64应用程序位去了眼前.当时我看到苹果公布的官方数据iOS7.x的SDK支撑64位应用程序.而内置的应用程序已经64位置. 我记得自己刚刚接触电脑时还有16位的系统,指针 ...

  7. IPHONE 64位和32位

    参考段一:iPhone 5没有64位的,只有32位架构,苹果是从iPhone 5s开始对全线移动产品使用64位架构.iPhone 5s发布之后的所有产品都是64位的使用LUAJIT或LUAC都可以对L ...

  8. 介绍 32 位和 64 位版本的 Microsoft Office 2010

    在使用 64 位版本的 Office 2010 运行现有解决方案时存在两个基本问题: Office 2010 中的本机 64 位进程无法加载 32 位二进制文件.在使用现有 Microsoft Act ...

  9. C++:基础篇-32位和64位系统区别及字节数

    今儿面试了一个刚刚毕业的,但是不知道一个int.long.double这几个都是多少位,我给你们总结一下哈: 常用数据类型对应字节数  可用如sizeof(char),sizeof(char*)等得出 ...

  10. ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构

    ★PART1:32位的x86处理器执行方式和架构 1. 寄存器的拓展(IA-32) 从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存 ...

随机推荐

  1. GIL和池的概念

    1.GIL概念 1. 什么是GIL(为Cpython解释器) GIL本身就是一把互斥锁. 原理都一样. 都是让并发的线程同一时间只能执行一个 所以有了GIL的存在. 同一进程下的多个线程同一时刻只能有 ...

  2. API Gateway vs Load Balancer:选择适合你的网络流量管理组件

    本文从对比了 API Gateway 和 Load Balancer 的功能区别,帮助读者更好地了解他们在系统架构中扮演的角色. 作者陈泵,API7.ai 技术工程师. 原文链接 由于互联网技术的发展 ...

  3. DeFi-DEX-借贷

    不知道为什么上课的笔记没保存上55555 看看ppt和视频吧(

  4. [双目视差] 立体校正源码分析(opencv)

    文章目录 [双目视差] 立体校正源码分析(opencv) 一.源码解析 二.源码中的方法 [双目视差] 立体校正源码分析(opencv) 一.源码解析 立体校正:把实际中非共面行对准的两幅图像,校正成 ...

  5. Python-趣味小程序

    1.效果 2.代码 import sys import time def print_act(word): #print('\n'+' '+'\r') #让光标回到行首 sys.stdout.writ ...

  6. 【Docker】安装及部署

    一.Ubuntu使用apt安装Docker 官方安装文档:https://docs.docker.com/engine/install/ubuntu/ 1.准备安装环境 [root@Docker-Ub ...

  7. Vue 前端开发团队风格指南(史上最全)

    Vue官网的风格指南按照优先级(依次为必要.强烈推荐.推荐.谨慎使用)分类,本文根据项目实际情况整理了一份适用于团队开发的vue风格指南,供大家参考. 一.命名规范 常用的命名规范: camelCas ...

  8. Oracle 定时任务job实际应用

    目录 一.Oracle定时任务简介 二.dbms_job涉及到的知识点 三.初始化相关参数job_queue_processes 四.实际创建一个定时任务(一分钟执行一次),实现定时一分钟往表中插入数 ...

  9. 2022-11-07:给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边。 图用一个大小为 n 下标从 0 开始的数组 edges 表示, 节点 i 到

    2022-11-07:给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边. 图用一个大小为 n 下标从 0 开始的数组 edges 表示, 节点 i 到 ...

  10. 2022-05-29:为了不断提高用户使用的体验,开发团队正在对产品进行全方位的开发和优化。 已知开发团队共有若干名成员,skills[i] 表示第 i 名开发人员掌握技能列表。 如果两名成员各自拥有

    2022-05-29:为了不断提高用户使用的体验,开发团队正在对产品进行全方位的开发和优化. 已知开发团队共有若干名成员,skills[i] 表示第 i 名开发人员掌握技能列表. 如果两名成员各自拥有 ...