如何检查一个系统是大端还是小端?

111
如何检查一个系统是大端还是小端?

1
C语言:https://dev59.com/uHI95IYBdhLWcg3w5iU4C++语言:https://dev59.com/_XNA5IYBdhLWcg3wVcT6Shell脚本:https://serverfault.com/questions/163487/how-to-tell-if-a-linux-system-is-big-endian-or-little-endian - Ciro Santilli OurBigBook.com
20个回答

116

在C和C++中

int n = 1;
// little endian if true
if(*(char *)&n == 1) {...}

另请参阅:Perl版本


17
回答不错,但这里有一个清晰的图解可以解释正在发生的事情:https://dev59.com/1Wcs5IYBdhLWcg3wgkMQ#12792301 - gsgx
4
为什么我们不能只使用(char)n == 1呢?为什么我们必须获取地址,将其转换为char指针,然后解引用?当使用(char)n时,不会隐式地完成此操作吗? - J...S
5
只使用字符是不起作用的。将其转换为字符会导致系统从整数转换为字符。它总是返回true。使用指针转换和解引用将指针放置在N的第一个字节上,然后解引用第一个字节。 - Garret Gang
2
一个强制类型转换并不等同于一个数值转换。如果是大端字节序,那么N的第一个字节为零 - 那么这怎么会导致结果为真呢? - belwood
这个答案以及下面所有使用程序查找字节序的答案都是错误的!!事实上,机器是大端还是小端对程序员来说是隐藏的,由编译器决定。在大端机器上,类型转换将再次返回1,因为编译器知道机器是大端的,强制转换将获取更高的内存地址。 - Hemanth
显示剩余4条评论

70

使用Python:

from sys import byteorder
print(byteorder)
# will print 'little' if little endian

18

另一个使用联合(union)的 C 代码

union {
    int i;
    char c[sizeof(int)];
} x;
x.i = 1;
if(x.c[0] == 1)
    printf("little-endian\n");
else    printf("big-endian\n");

这与 belwood 使用的逻辑相同。


3
我认为这并不符合标准规范:你只能从你最后写入的枚举字段中读取,否则可能会出现未定义行为,不知道我理解得对不对? - worenga
1
联合体在标准中未指定“对齐方式”,这不是正确的解决方案(它可能在特定操作系统/编译器中偶然起作用)。 - Mariusz Jaskółka
请问有人能解释一下上面程序的逻辑吗?如果将成员变量i初始化为x.1=1,那么x.c[0]怎么会变成1呢?我是不是漏掉了什么关键点?我的理解是联合体占用最大数据类型的内存,根据这个我们可以访问它。只能访问一个成员。非常感谢任何回复。 - Vivek Singh
1
@VivekSingh,正如你所说,联合体会占用最大数据类型的内存,我们可以根据这个来访问它。因此,两种数据类型的内存大小相同。我们将其作为int类型进行访问,并将其分配为1。因此,在4字节中,只有1字节部分将具有单个1。当我们将其作为char类型访问时,它只占用1字节。 - Neeraj

16
在C++20中使用 std::endian
#include <bit>
#include <iostream>

int main() {
    if constexpr (std::endian::native == std::endian::little)
        std::cout << "little-endian";
    else if constexpr (std::endian::native == std::endian::big)
        std::cout << "big-endian";
    else
        std::cout << "mixed-endian";
}

14

使用 Perl 的单行代码(Perl 应该已经默认安装在几乎所有系统上):

perl -e 'use Config; print $Config{byteorder}'

如果输出以1(最低有效字节)开头,则为小端系统。如果输出以更高位数字(最高有效字节)开头,则为大端系统。请参阅Config模块的文档。


12
如果您使用的是.NET:请检查BitConverter.IsLittleEndian的值。

9
在Rust中(无需使用crate或use语句) 在函数体内:
if cfg!(target_endian = "big") {
    println!("Big endian");
} else {
    println!("Little endian");
}

在函数体外:

#[cfg(target_endian = "big")]
fn print_endian() {
    println!("Big endian")
}

#[cfg(target_endian = "little")]
fn print_endian() {
    println!("Little endian")
}

这就是 byteorder crate 内部的实现方式:https://docs.rs/byteorder/1.3.2/src/byteorder/lib.rs.html#1877


第一个示例中应该使用闭合的花括号而不是方括号。 - Miles Elam

5
在 PowerShell 中
[System.BitConverter]::IsLittleEndian

4
在Linux中,
static union { char c[4]; unsigned long mylong; } endian_test = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.mylong)

if (ENDIANNESS == 'l') /* little endian */
if (ENDIANNESS == 'b') /* big endian */

1
它与Neeraj版本有何不同? - phuclv

3

一份C++解决方案:

namespace sys {

const unsigned one = 1U;

inline bool little_endian()
{
    return reinterpret_cast<const char*>(&one) + sizeof(unsigned) - 1;
}

inline bool big_endian()
{
    return !little_endian();
}

} // sys

int main()
{
    if(sys::little_endian())
        std::cout << "little";
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接