首页 文章

是什么让系统成为little-endian或big-endian?

提问于
浏览
12

我对系统/ cpu /程序的字节顺序感到困惑 .
所以我必须提出一些问题才能让我明白 .

问题1

如果我只在我的C程序中使用 char 类型:

void main()
{
    char c = 'A';
    char* s = "XYZ";    
}

然后将此程序编译为名为 a.out 的可执行二进制文件 .
a.out 可以在little-endian和big-endian系统上运行吗?

问题2

如果我的Windows XP系统是little-endian,我可以在VMWare / VirtualBox中安装大端Linux系统吗?是什么让系统成为little-endian或big-endian?

问题3

如果我想编写一个与字节顺序无关的C程序,我需要考虑什么?

6 回答

  • 2

    a.out可以运行在little-endian和big-endian系统上吗?

    不,因为几乎任何两个具有不同字节序的CPU都不会运行相同的指令集 . C不是Java;你没有编译成被编译或解释的东西 . 您编译为特定CPU的程序集 . endian-ness是CPU的一部分 .

    但这不是endian问题 . 您可以为不同的CPU编译该程序,这些可执行文件可以在各自的CPU上正常工作 .

    什么使系统成为little-endian或big-endian?

    就C或C而言,CPU . 计算机中的不同处理单元实际上可以有不同的端序(GPU可以是大端,而CPU是小端),但这有点不常见 .

    如果我想编写一个字节顺序独立的C程序,我需要考虑什么?

    只要您遵守C或C规则,您就不必关心字节序问题 .

    当然,您也无法将文件直接加载到POD结构中 . 或者读取一系列字节,假装它是一系列无符号短路,然后将其作为UTF-16编码的字符串处理 . 所有这些都进入了实现定义行为的领域 .

    有's a difference between 1564095 and 1564096 behavior. When the C and C++ spec say something is 1564097 , it basically means all manner of brokenness can ensue. If you keep doing it, (and your program doesn' t崩溃)你可能得到不一致的结果 . 当它表示实现定义了某些内容时,您将获得该实现的一致结果 .

    如果在VC2010中编译x86,假装一个字节数组是无符号短数组(即: unsigned char *byteArray = ...; unsigned short *usArray = (unsigned short*)byteArray )由实现定义 . 在编译big-endian CPU时,你会得到与编译little-endian CPU时不同的答案 .

    通常,endian问题是可以本地化为输入/输出系统的问题 . 网络,文件读取等 . 应该在代码库的极端处理它们 .

  • 3

    Question 1:

    a.out可以运行在little-endian和big-endian系统上吗?

    不会 . 因为 a.out 已经针对它所针对的任何架构进行了编译 . 它不会在与其不兼容的另一个架构上运行 .

    但是,该简单程序的源代码没有什么可能在不同的端机器上破坏 .

    所以它是(源)将正常工作 . (嗯......除了 void main() ,你应该使用 int main() 代替)

    Question 2:

    如果我的WindowsXP系统是little-endian,我可以在VMWare / VirtualBox中安装大端Linux系统吗?

    Endian-ness由硬件决定,而不是OS . 因此,无论您在其上安装什么(本机)VM,它都将与主机相同 . (因为x86都是小端)

    什么使系统成为little-endian或big-endian?

    这是一个在小端与大端上表现不同的东西的例子:

    uint64_t a = 0x0123456789abcdefull;
    uint32_t b = *(uint32_t*)&a;
    printf("b is %x",b)
    

    *请注意,这违反了严格别名,仅用于演示目的 .

    Little Endian : b is 89abcdef
    Big Endian    : b is 1234567
    

    在little-endian上, a 的低位存储在最低地址 . 因此,当您将 a 作为32位整数访问时,您将读取它的低32位 . 在big-endian上,您将读取高32位 .

    Question 3:

    如果我想编写一个字节顺序独立的C程序,我需要考虑什么?

    只需遵循标准的C规则,就像我上面展示的例子一样,不要做任何丑陋的事情 . 避免未定义的行为,避免类型惩罚...

  • 20

    Little-endian / big-endian是硬件的属性 . 通常,为一个硬件编译的二进制代码不能在另一个硬件上运行,除了在解释机器代码的虚拟化环境中,并为其模拟目标硬件 . 有双端CPU(例如ARM,IA-64)具有改变字节序的开关 .

    就字节顺序无关编程而言,唯一需要做的就是处理联网 . 有一些函数,如ntohl and htonl,可以帮助您转换硬件's byte order to network'的字节顺序 .

  • 1

    首先要澄清的是,endianness是硬件属性,而不是软件/ OS属性,因此WinXP和Linux不是big-endian或little endian,而是它们运行的硬件是big-endian或little endian .

    字节顺序是对字节存储在数据类型中的顺序的描述 . big-endian系统首先存储最重要(读取最大值)值,而little-endian系统首先存储最低有效字节 . 并非强制要求每个数据类型与系统上的其他数据类型相同,因此您可以使用混合端系统 .

    一个小端的程序不会在大端系统上运行,但是对于可用的指令集而言,它比编译它的系统的字节序更多 .

    如果要编写独立于字节顺序的程序,则只需要不依赖于数据的字节顺序 .

  • 2

    1:编译器的输出取决于您提供的选项以及是否使用交叉编译器 . 默认情况下,它应该在您正在编译它的操作系统上运行,而不是在其他操作系统上运行(可能甚至不是同一类型的其他操作系统;例如,并非所有Linux二进制文件都在所有Linux安装上运行) . 在大型项目中,这将是您最不关心的问题,因为库等需要在每个系统上进行不同的构建和链接 . 使用正确的构建系统(如make)将处理大部分内容而无需担心 .

    2:虚拟机以这样一种方式抽象硬件,即基本上允许任何东西在其他任何东西中运行 . 只要操作系统在相同的硬件上运行并支持正在使用的虚拟化模型,操作系统如何管理内存就不重要了 . 字节顺序表示字节顺序;如果是左右或左右(或其他一些格式) . 一些硬件支持两者兼容,虚拟化允许两者在这种情况下共存(尽管我不知道这有什么用,除了它在理论上是可能的) . 但是,Linux适用于许多不同的体系结构(以及除Ixxx以外的Windows),因此情况更复杂 .

    3:如果你使用原始内存,例如使用二元运算符,你可能会把自己放在依赖于字节序的位置 . 但是,大多数现代编程都处于比这更高的水平 . 因此,您可能会注意到,如果您遇到可能会强加基于字节序限制的内容 . 如果需要这样,您始终可以使用预处理器为两个字节序实现选项 .

  • 8

    系统的字节序确定如何解释字节,因此将哪个位视为"first"以及"last" .

    只有在从程序外部的某些源(如磁盘或网络)加载或保存时,才需要关心它 .

相关问题