【问题标题】:Big/Little endian detector (C++) [duplicate]大/小端检测器(C++)[重复]
【发布时间】:2012-01-12 21:16:02
【问题描述】:

可能重复:
Detecting endianness programmatically in a C++ program

我正在处理一个 C++ 项目,该项目要求我知道系统是大端还是小端。

我想出了一些我认为可以成功检测到这一点的代码!不过,这是我第一次真正这样编程,我想知道这是否真的有效:

int fourbytesint = 0;//Initialize four bytes
((char*)&fourbytesint)[0] = 1;//Get the first byte of our four bytes
//(Pretend the int is an array of 4 bytes, get the first byte)

//Depending upon the endian, this will be a reasonably small number, or an unreasonably large number
if (fourbytesint > 1000)
{
    cout << "Big endian!" << endl;
}
else
{
    cout << "Little Endian!" << endl;
}

另外,我的导师告诉我,C++ 中的 char 可以用来存储字节。我对此有点警惕,正如我在 Java 等语言中所知道的那样,char 通常存储两个字节的 Unicode 字符。

我在上面的例子中使用 char 作为字节是否正确?

【问题讨论】:

  • 您确定需要知道您的字节顺序吗?干什么用的?
  • 这已经被问过很多次了。 stackoverflow.com/q/1001307/1078151
  • 我正在为学校做作业,我的老师让我写一些与他的数据结构交互的东西。他的数据结构是原始字节数据块的形式,并且由于其性质,依赖于大端/小端。他提供了该数据的两份副本,一份用于大端系统,一份用于小端系统。我在 mac OSX 上运行,因此很难判断使用哪一个。我只是想让我的代码为我选择。
  • @ThatChuckGuy 我或多或少地在问我的代码是否能工作
  • @GeorgesOatesLarsen,如果您使用的是 intel mac(即过去几年出售的任何 mac),请使用 little endian

标签: c++ char byte


【解决方案1】:

恕我直言,最简单的方法是使用htonl() 函数。

在大端机器上,htonl() 将是空操作,您的值不会改变。

【讨论】:

  • 但是,您必须小心在测试时传递一个所有八位字节都不同的值,以正确检测混合端系统。
【解决方案2】:

是的,您的检测方法有效。 (尽管您可能能够以独立于字节序的方式编写代码,例如使用htonl(),正如 Brian Roach 所建议的那样。即使大字节序和小字节序不是唯一的选择,这也将使您的代码工作。)

是的,C++ 中的char 是一个字节。通过定义 sizeof(char) == 1

编辑:正如 cmets 中所指出的,sizeof(char)==sizeof(int) 是可能的。您的代码会将其检测为大端。但是当一个类型的存储不跨越多个可寻址位置时,字节序的概念就没有意义了。也就是说,由于“大端”意味着 int 的“子单元”是有序的,因此更重要的单元位于不那么重要的单元之前,因此将该术语用于只有一个“子单元”的东西是没有意义的-单元'。不过,您可以为任一分支编写代码,以便它处理这种情况,然后就没有关系了。

【讨论】:

  • 啊,谢谢你,你回答了我所有的问题! :)
  • 虽然 sizeof(char) == 1 根据定义成立,但绝对不能保证 sizeof(int) != sizeof(char),所以这并没有真正说明什么(我想我已经读过一个平台,其中 char 是 64 位)
  • @Grizzly char 是 C++ 中最小可寻址单元的大小,这就是字节的定义。 (例如,有些系统有 9 位字节,如果你说的是真的,显然是 64 位字节)。
  • @bames53:我只是在说sizeof(char) 总是蜂拥而至并不能真正帮助 OP 代码
  • @bames53,Grizzly 是正确的,在某些平台上,sizeof(int) == sizeof(char),这意味着 sizeof(int) == 1(以及 CHAR_BIT &gt;= 16)。这通常只发生在像 DSP 这样奇怪的嵌入式平台上,但确实会发生,并且一个旨在高度可移植的库必须考虑这种奇怪的情况。
【解决方案3】:

在 Mac OS X 上,您的代码可以检测小端或大端系统。

从历史上看,还有另一个类别 - “混合字节序”系统,其中字节的顺序很奇怪(不是 4321 或 1234,而是像 2143 之类的更奇怪的东西)。在这种情况下,您的代码可能无法检测到这一点 - fourbytesint 可能最终成为 256。最好对这样的代码使用相等检查。但是,由于 OS X 不能在混合端系统上运行,因此对于您的目的而言,这不是一个实际问题。

此外,在 OS X 上,最好使用htonl(来自&lt;arpa/inet.h&gt;)进行此检测。 htonl 在许多类 unix 系统上可以在编译时进行优化,从而消除此类测试的运行时开销。

【讨论】:

  • 最详细的答案!我希望您接受,但不同的答案直接回答了我的两个问题。感谢您提供有关混合字节序的信息 :) 我希望我能给答案加星标
  • @GeorgesOatesLarsen 你可以:) 只需点击答案左上角的向上箭头。
【解决方案4】:

我会执行以下操作来检查字节顺序:

bool isLittleEndian()
{
   unsigned num = 0xABCD; 

   return *((unsigned char*)&num) == 0xCD;
}

正如其他人所说,sizeof(char) 确实等于 1。

C++ 标准中关于 unsigned int 的所有说法是它能够保存从 00xFFFF 的值(基本上至少 2 个字节大小),所以这就是为什么我使用值 0xABCD 而不是一个使用 4 个字节(也可以使用 0xCD)。

并且unsigned char 而不是signed 更适合表示字节,因为您很可能想要原始的unsigned 字节值。

【讨论】:

  • 谢谢哥们。我将使用您的解决方案并注明出处。
【解决方案5】:

反过来可能会更容易。创建一个 int,将其设置为值 1。然后使用字节指针将其拆分为字节,并检查它是第一个还是最后一个值为 1 的字节(其他字节将为 0)。

【讨论】:

    【解决方案6】:

    您的代码是正确的,但它太复杂了。
    这更简单,更容易阅读。

    short var = 0x1;  
    char * byte = (char *) &var; 
    if(byte[0] > 0){
       cout << "Little Endian";  
    }
    else{  
       cout << "Big Endian";  
    }
    

    【讨论】:

    • 我会说我们的代码在复杂性和可读性方面大致相同,尽管使用的是 short 而不是 int,有趣的概念
    • Depends.Your code 可能对你和我来说都很清楚,但是对于其他人来说第二行可能会令人困惑(我当然会避免它)。我一直认为代码应该易于理解下一个开发者
    • 对,这正是我的意思^^
    猜你喜欢
    • 2012-09-29
    • 2014-03-07
    • 1970-01-01
    • 2016-08-10
    • 2021-10-29
    • 2010-10-18
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多