宏定义确定大端还是小端机?

发布于 2024-08-18 03:31:59 字数 231 浏览 8 评论 0原文

是否有一行宏定义来确定机器的字节顺序?我正在使用以下代码,但将其转换为宏会太长:

unsigned char test_endian( void )
{
    int test_var = 1;
    unsigned char *test_endian = (unsigned char*)&test_var;

    return (test_endian[0] == 0);
}

Is there a one line macro definition to determine the endianness of the machine? I am using the following code but converting it to macro would be too long:

unsigned char test_endian( void )
{
    int test_var = 1;
    unsigned char *test_endian = (unsigned char*)&test_var;

    return (test_endian[0] == 0);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(24

梨涡少年 2024-08-25 03:31:59

支持任意字节顺序的代码,准备放入名为 order32.h 的文件中:

#ifndef ORDER32_H
#define ORDER32_H

#include <limits.h>
#include <stdint.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

enum
{
    O32_LITTLE_ENDIAN = 0x03020100ul,
    O32_BIG_ENDIAN = 0x00010203ul,
    O32_PDP_ENDIAN = 0x01000302ul,      /* DEC PDP-11 (aka ENDIAN_LITTLE_WORD) */
    O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 (aka ENDIAN_BIG_WORD) */
};

static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
    { { 0, 1, 2, 3 } };

#define O32_HOST_ORDER (o32_host_order.value)

#endif

您可以通过以下方式检查小端系统:

O32_HOST_ORDER == O32_LITTLE_ENDIAN

Code supporting arbitrary byte orders, ready to be put into a file called order32.h:

#ifndef ORDER32_H
#define ORDER32_H

#include <limits.h>
#include <stdint.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

enum
{
    O32_LITTLE_ENDIAN = 0x03020100ul,
    O32_BIG_ENDIAN = 0x00010203ul,
    O32_PDP_ENDIAN = 0x01000302ul,      /* DEC PDP-11 (aka ENDIAN_LITTLE_WORD) */
    O32_HONEYWELL_ENDIAN = 0x02030001ul /* Honeywell 316 (aka ENDIAN_BIG_WORD) */
};

static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
    { { 0, 1, 2, 3 } };

#define O32_HOST_ORDER (o32_host_order.value)

#endif

You would check for little endian systems via

O32_HOST_ORDER == O32_LITTLE_ENDIAN
无悔心 2024-08-25 03:31:59

如果您有一个支持 C99 复合文字的编译器:

#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1})

或:

#define IS_BIG_ENDIAN (!(union { uint16_t u16; unsigned char c; }){ .u16 = 1 }.c)

但一般来说,您应该尝试编写不依赖于主机平台字节序的代码。


ntohl() 与主机字节序无关的实现示例:

uint32_t ntohl(uint32_t n)
{
    unsigned char *np = (unsigned char *)&n;

    return ((uint32_t)np[0] << 24) |
        ((uint32_t)np[1] << 16) |
        ((uint32_t)np[2] << 8) |
        (uint32_t)np[3];
}

If you have a compiler that supports C99 compound literals:

#define IS_BIG_ENDIAN (!*(unsigned char *)&(uint16_t){1})

or:

#define IS_BIG_ENDIAN (!(union { uint16_t u16; unsigned char c; }){ .u16 = 1 }.c)

In general though, you should try to write code that does not depend on the endianness of the host platform.


Example of host-endianness-independent implementation of ntohl():

uint32_t ntohl(uint32_t n)
{
    unsigned char *np = (unsigned char *)&n;

    return ((uint32_t)np[0] << 24) |
        ((uint32_t)np[1] << 16) |
        ((uint32_t)np[2] << 8) |
        (uint32_t)np[3];
}
晚风撩人 2024-08-25 03:31:59

没有标准,但在许多系统上,包括 将为您提供一些需要查找的定义。

There is no standard, but on many systems including <endian.h> will give you some defines to look for.

携君以终年 2024-08-25 03:31:59

要在运行时检测字节顺序,您必须能够引用内存。如果您坚持使用标准 C,则在内存中声明变量需要一个语句,但返回一个值需要一个表达式。我不知道如何在单个宏中执行此操作 - 这就是 gcc 具有扩展名的原因 :-)

如果您愿意拥有 .h 文件,则可以定义

static uint32_t endianness = 0xdeadbeef; 
enum endianness { BIG, LITTLE };

#define ENDIANNESS ( *(const char *)&endianness == 0xef ? LITTLE \
                   : *(const char *)&endianness == 0xde ? BIG \
                   : assert(0))

,然后可以使用 ENDIANNESS 宏,如你所愿。

To detect endianness at run time, you have to be able to refer to memory. If you stick to standard C, declarating a variable in memory requires a statement, but returning a value requires an expression. I don't know how to do this in a single macro—this is why gcc has extensions :-)

If you're willing to have a .h file, you can define

static uint32_t endianness = 0xdeadbeef; 
enum endianness { BIG, LITTLE };

#define ENDIANNESS ( *(const char *)&endianness == 0xef ? LITTLE \
                   : *(const char *)&endianness == 0xde ? BIG \
                   : assert(0))

and then you can use the ENDIANNESS macro as you will.

彡翼 2024-08-25 03:31:59

如果您只想依赖预处理器,则必须找出预定义符号的列表。预处理器算术没有寻址的概念。

Mac 上的 GCC 定义了 __LITTLE_ENDIAN____BIG_ENDIAN__

$ gcc -E -dM - < /dev/null |grep ENDIAN
#define __LITTLE_ENDIAN__ 1

然后,您可以根据平台检测添加更多预处理器条件指令,例如 #ifdef _WIN32代码>等

If you want to only rely on the preprocessor, you have to figure out the list of predefined symbols. Preprocessor arithmetics has no concept of addressing.

GCC on Mac defines __LITTLE_ENDIAN__ or __BIG_ENDIAN__

$ gcc -E -dM - < /dev/null |grep ENDIAN
#define __LITTLE_ENDIAN__ 1

Then, you can add more preprocessor conditional directives based on platform detection like #ifdef _WIN32 etc.

梦境 2024-08-25 03:31:59

我相信这就是我们所要求的。
我只在 msvc 下的小端机器上测试了这个。
请有人在大端机器上确认。

    #define LITTLE_ENDIAN 0x41424344UL 
    #define BIG_ENDIAN    0x44434241UL
    #define PDP_ENDIAN    0x42414443UL
    #define ENDIAN_ORDER  ('ABCD') 

    #if ENDIAN_ORDER==LITTLE_ENDIAN
        #error "machine is little endian"
    #elif ENDIAN_ORDER==BIG_ENDIAN
        #error "machine is big endian"
    #elif ENDIAN_ORDER==PDP_ENDIAN
        #error "jeez, machine is PDP!"
    #else
        #error "What kind of hardware is this?!"
    #endif

作为旁注(特定于编译器),使用激进的编译器,您可以使用“死代码消除”优化来实现与编译时 #if 相同的效果,如下所示

    unsigned yourOwnEndianSpecific_htonl(unsigned n)
    {
        static unsigned long signature= 0x01020304UL; 
        if (1 == (unsigned char&)signature) // big endian
            return n;
        if (2 == (unsigned char&)signature) // the PDP style
        {
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        if (4 == (unsigned char&)signature) // little endian
        {
            n = (n << 16) | (n >> 16);
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        // only weird machines get here
        return n; // ?
    }

:编译器在编译时识别常量值,完全删除 if (false) { ... } 中的代码,并替换类似 if (true) { foo(); 的代码。 }foo(); 最坏的情况:编译器不进行优化,您仍然会得到正确的代码,但速度会慢一些。

I believe this is what was asked for.
I only tested this on a little endian machine under msvc.
Someone plese confirm on a big endian machine.

    #define LITTLE_ENDIAN 0x41424344UL 
    #define BIG_ENDIAN    0x44434241UL
    #define PDP_ENDIAN    0x42414443UL
    #define ENDIAN_ORDER  ('ABCD') 

    #if ENDIAN_ORDER==LITTLE_ENDIAN
        #error "machine is little endian"
    #elif ENDIAN_ORDER==BIG_ENDIAN
        #error "machine is big endian"
    #elif ENDIAN_ORDER==PDP_ENDIAN
        #error "jeez, machine is PDP!"
    #else
        #error "What kind of hardware is this?!"
    #endif

As a side note (compiler specific), with an aggressive compiler you can use "dead code elimination" optimization to achieve the same effect as a compile time #if like so:

    unsigned yourOwnEndianSpecific_htonl(unsigned n)
    {
        static unsigned long signature= 0x01020304UL; 
        if (1 == (unsigned char&)signature) // big endian
            return n;
        if (2 == (unsigned char&)signature) // the PDP style
        {
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        if (4 == (unsigned char&)signature) // little endian
        {
            n = (n << 16) | (n >> 16);
            n = ((n << 8) & 0xFF00FF00UL) | ((n>>8) & 0x00FF00FFUL);
            return n;
        }
        // only weird machines get here
        return n; // ?
    }

The above relies on the fact that the compiler recognizes the constant values at compile time, entirely removes the code within if (false) { ... } and replaces code like if (true) { foo(); } with foo(); The worst case scenario: the compiler does not do the optimization, you still get correct code but a bit slower.

望笑 2024-08-25 03:31:59

如果您正在寻找编译时测试并且正在使用 gcc,您可以执行以下操作:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

请参阅 gcc 文档 了解更多信息。

If you are looking for a compile time test and you are using gcc, you can do:

#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__

See gcc documentation for more information.

挽清梦 2024-08-25 03:31:59

事实上,您可以使用复合文字 (C99) 来访问临时对象的内存:

#define IS_LITTLE_ENDIAN (1 == *(unsigned char *)&(const int){1})

GCC 将在编译时评估该文字。

You can in fact access the memory of a temporary object by using a compound literal (C99):

#define IS_LITTLE_ENDIAN (1 == *(unsigned char *)&(const int){1})

Which GCC will evaluate at compile time.

递刀给你 2024-08-25 03:31:59

如果你转储预处理器#defines,

gcc -dM -E - < /dev/null
g++ -dM -E -x c++ - < /dev/null

你通常可以找到对你有帮助的东西。具有编译时逻辑。

#define __LITTLE_ENDIAN__ 1
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__

然而,不同的编译器可能有不同的定义。

If you dump the preprocessor #defines

gcc -dM -E - < /dev/null
g++ -dM -E -x c++ - < /dev/null

You can usually find stuff that will help you. With compile time logic.

#define __LITTLE_ENDIAN__ 1
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__

Various compilers may have different defines however.

少钕鈤記 2024-08-25 03:31:59

“C 网络库”提供了处理字节序的函数。即 htons()、htonl()、ntohs() 和 ntohl() ...其中 n 是“网络”(即大端字节序),h 是“主机”(即运行该网络的机器的字节序)代码)。

这些明显的“函数”(通常)被定义为宏[参见],因此使用它们没有运行时开销。

以下宏使用这些“函数”来评估字节序。

#include <arpa/inet.h>
#define  IS_BIG_ENDIAN     (1 == htons(1))
#define  IS_LITTLE_ENDIAN  (!IS_BIG_ENDIAN)

另外:

我唯一需要知道系统的字节序是当我将一个变量[到文件/其他]写出时,该变量可能会被另一个未知字节序的系统读入(对于交叉字节序) -平台兼容性)...在这些情况下,您可能更喜欢直接使用 endian 函数:

#include <arpa/inet.h>

#define JPEG_MAGIC  (('J'<<24) | ('F'<<16) | ('I'<<8) | 'F')

// Result will be in 'host' byte-order
unsigned long  jpeg_magic = JPEG_MAGIC;

// Result will be in 'network' byte-order (IE. Big-Endian/Human-Readable)
unsigned long  jpeg_magic = htonl(JPEG_MAGIC);

The 'C network library' offers functions to handle endian'ness. Namely htons(), htonl(), ntohs() and ntohl() ...where n is "network" (ie. big-endian) and h is "host" (ie. the endian'ness of the machine running the code).

These apparent 'functions' are (commonly) defined as macros [see <netinet/in.h>], so there is no runtime overhead for using them.

The following macros use these 'functions' to evaluate endian'ness.

#include <arpa/inet.h>
#define  IS_BIG_ENDIAN     (1 == htons(1))
#define  IS_LITTLE_ENDIAN  (!IS_BIG_ENDIAN)

In addition:

The only time I ever need to know the endian'ness of a system is when I write-out a variable [to a file/other] which may be read-in by another system of unknown endian'ness (for cross-platform compatability) ...In cases such as these, you may prefer to use the endian functions directly:

#include <arpa/inet.h>

#define JPEG_MAGIC  (('J'<<24) | ('F'<<16) | ('I'<<8) | 'F')

// Result will be in 'host' byte-order
unsigned long  jpeg_magic = JPEG_MAGIC;

// Result will be in 'network' byte-order (IE. Big-Endian/Human-Readable)
unsigned long  jpeg_magic = htonl(JPEG_MAGIC);
離人涙 2024-08-25 03:31:59

使用内联函数而不是宏。此外,您需要在内存中存储一​​些内容,这是宏的一个不太好的副作用。

您可以使用静态或全局变量将其转换为短宏,如下所示:

static int s_endianess = 0;
#define ENDIANESS() ((s_endianess = 1), (*(unsigned char*) &s_endianess) == 0)

Use an inline function rather than a macro. Besides, you need to store something in memory which is a not-so-nice side effect of a macro.

You could convert it to a short macro using a static or global variable, like this:

static int s_endianess = 0;
#define ENDIANESS() ((s_endianess = 1), (*(unsigned char*) &s_endianess) == 0)
-残月青衣踏尘吟 2024-08-25 03:31:59

虽然没有可移植的 #define 或依赖的东西,但平台确实提供了用于与“主机”字节序相互转换的标准函数。

通常,您使用“网络字节序”(BIG 字节序)进行存储(到磁盘或网络),并使用主机字节序(在 x86 上为字节序)进行本地计算)。您可以使用 htons()ntohs() 及其朋友在两者之间进行转换。

Whilst there is no portable #define or something to rely upon, platforms do provide standard functions for converting to and from your 'host' endian.

Generally, you do storage - to disk, or network - using 'network endian', which is BIG endian, and local computation using host endian (which on x86 is LITTLE endian). You use htons() and ntohs() and friends to convert between the two.

纸短情长 2024-08-25 03:31:59

不要忘记字节顺序并不是故事的全部 - char 的大小可能不是 8 位(例如 DSP),不保证二进制补码否定(例如 Cray),可能需要严格对齐(例如,SPARC,ARM 在未对齐时也会跳入中端),等等。

针对特定的CPU 架构可能是一个更好的主意。

例如:

#if defined(__i386__) || defined(_M_IX86) || defined(_M_IX64)
  #define USE_LITTLE_ENDIAN_IMPL
#endif

void my_func()
{
#ifdef USE_LITTLE_ENDIAN_IMPL
  // Intel x86-optimized, LE implementation
#else
  // slow but safe implementation
#endif
}

请注意,不幸的是,该解决方案也不是超可移植的,因为它取决于特定于编译器的定义(没有标准,但是 这里是此类定义的一个很好的汇编)。

Don't forget that endianness is not the whole story - the size of char might not be 8 bits (e.g. DSP's), two's complement negation is not guaranteed (e.g. Cray), strict alignment might be required (e.g. SPARC, also ARM springs into middle-endian when unaligned), etc, etc.

It might be a better idea to target a specific CPU architecture instead.

For example:

#if defined(__i386__) || defined(_M_IX86) || defined(_M_IX64)
  #define USE_LITTLE_ENDIAN_IMPL
#endif

void my_func()
{
#ifdef USE_LITTLE_ENDIAN_IMPL
  // Intel x86-optimized, LE implementation
#else
  // slow but safe implementation
#endif
}

Note that this solution is also not ultra-portable unfortunately, as it depends on compiler-specific definitions (there is no standard, but here's a nice compilation of such definitions).

金兰素衣 2024-08-25 03:31:59
#include <stdint.h>
#define IS_LITTLE_ENDIAN (*(uint16_t*)"\0\1">>8)
#define IS_BIG_ENDIAN (*(uint16_t*)"\1\0">>8)
#include <stdint.h>
#define IS_LITTLE_ENDIAN (*(uint16_t*)"\0\1">>8)
#define IS_BIG_ENDIAN (*(uint16_t*)"\1\0">>8)
z祗昰~ 2024-08-25 03:31:59

这个问题对于cpp来说也是实际的,所以我在这里问。

#if __cplusplus > 201703L

#include <bit>
#include <iostream>

using namespace std;

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

欲了解更多信息:https://en.cppreference.com/w /cpp/类型/字节序

This question is actual for cpp too, so I asked here.

ONLY #if __cplusplus > 201703L

#include <bit>
#include <iostream>

using namespace std;

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

For more info: https://en.cppreference.com/w/cpp/types/endian

沒落の蓅哖 2024-08-25 03:31:59

试试这个:

#include<stdio.h>        
int x=1;
#define TEST (*(char*)&(x)==1)?printf("little endian"):printf("Big endian")
int main()
{

   TEST;
}

Try this:

#include<stdio.h>        
int x=1;
#define TEST (*(char*)&(x)==1)?printf("little endian"):printf("Big endian")
int main()
{

   TEST;
}
兔姬 2024-08-25 03:31:59

在 C++20 中,头文件 中引入了枚举 std::endian

https://en.cppreference.com/w/cpp/types/endian

#include <bit>
#include <iostream>
 
int main() {
 
    if constexpr (std::endian::native == std::endian::big)
        std::cout << "big-endian\n";
    else if constexpr (std::endian::native == std::endian::little)
        std::cout << "little-endian\n";
    else std::cout << "mixed-endian\n";
}

In C++20 an enum std::endian in the header <bit> was introduced:

https://en.cppreference.com/w/cpp/types/endian

#include <bit>
#include <iostream>
 
int main() {
 
    if constexpr (std::endian::native == std::endian::big)
        std::cout << "big-endian\n";
    else if constexpr (std::endian::native == std::endian::little)
        std::cout << "little-endian\n";
    else std::cout << "mixed-endian\n";
}
想你的星星会说话 2024-08-25 03:31:59

请注意,这里的大多数答案都是不可移植的,因为今天的编译器将在编译时评估这些答案(取决于优化)并根据特定的字节顺序返回特定值,而实际的机器字节顺序可能有所不同。测试字节顺序的值永远不会到达系统内存,因此无论实际字节顺序如何,实际执行的代码都将返回相同的结果。

对于示例,在 ARM Cortex-M3 中,实现的字节顺序将反映在状态位 AIRCR.ENDIANNESS 中,并且编译器在编译时无法知道该值。

这里建议的一些答案的编译输出:

https://godbolt.org/z/GJGNE2 for 这个答案,

https://godbolt.org/z/Yv-pyJ for 这个答案,等等在。

要解决这个问题,您需要使用易失性限定符。 Yogeesh H T 的答案是最接近当今现实生活使用情况的答案,但由于 Christoph 建议了更全面的解决方案,因此对他的 answer 将使答案完整,只需将 易失性 添加到联合声明中:static const 易失性联合

这将确保存储和读取内存,这是确定字节顺序所必需的。

Please pay attention that most of the answers here are not portable, since compilers today will evaluate those answers in compilation time (depends on the optimization) and return a specific value based on a specific endianness, while the actual machine endianness can differ. The values on which the endianness is tested, won't never reach the system memory thus the real executed code will return the same result regardless of the actual endianness.

For example, in ARM Cortex-M3 the implemented endianness will reflect in a status bit AIRCR.ENDIANNESS and compiler cannot know this value in compile time.

Compilation output for some of the answers suggested here:

https://godbolt.org/z/GJGNE2 for this answer,

https://godbolt.org/z/Yv-pyJ for this answer, and so on.

To solve it you will need to use the volatile qualifier. Yogeesh H T's answer is the closest one for today's real life usage, but since Christoph suggests more comprehensive solution, a slight fix to his answer would make the answer complete, just add volatile to the union declaration: static const volatile union.

This would assure storing and reading from memory, which is needed to determine endianness.

海螺姑娘 2024-08-25 03:31:59

如果您的编译器支持复合文字并且您明确不使用 C++,则可以使用

#define BIG_ENDIAN      ((*(const char*)&(const int){0x01020304}) == 0x01)
#define LITTLE_ENDIAN   ((*(const char*)&(const int){0x01020304}) == 0x04)

这不需要声明任何运行时变量,我认为这使得它比大多数其他解决方案更干净

If your compiler supports compound literals and you are pointedly not using C++ you can use

#define BIG_ENDIAN      ((*(const char*)&(const int){0x01020304}) == 0x01)
#define LITTLE_ENDIAN   ((*(const char*)&(const int){0x01020304}) == 0x04)

This doesn't require the declaration of any runtime variables, which I think makes it a good deal cleaner than most of the other solutions

月野兔 2024-08-25 03:31:59
#include <stdio.h>

#define CHECK_FOR_ENDIANNESS (*(char*)&(unsigned int){1})

int main() {
    if (CHECK_FOR_ENDIANNESS) {
        printf("little-endian.\n");
    } else {
        printf("big-endian.\n");
    }
    return 0;
}

工作原理

Step #1  Create an unsigned int with a value of 1
                +----------+----------+----------+----------+
Memory Address  |  0x1000  |  0x1001  |  0x1002  |  0x1003  |
                +----------+----------+----------+----------+
Little:         |  01      |  00      |  00      |  00      |
                +----------+----------+----------+----------+
Big:            |  00      |  00      |  00      |  01      |
                +----------+----------+----------+----------+

Step #2  Cast the address to a char pointer (focuses on first byte)
                +----------+
Memory Address  |  0x1000  |
                +----------+
Little:         |  01      |
                +----------+
Big:            |  00      |
                +----------+

Step #3  Dereference the char pointer to get the value

Little:         Returns 1 (for little-endian)
Big:            Returns 0 (for big-endian)

演示

#include <stdio.h>

#define CHECK_FOR_ENDIANNESS (*(char*)&(unsigned int){1})

int main() {
    if (CHECK_FOR_ENDIANNESS) {
        printf("little-endian.\n");
    } else {
        printf("big-endian.\n");
    }
    return 0;
}

How It Works

Step #1  Create an unsigned int with a value of 1
                +----------+----------+----------+----------+
Memory Address  |  0x1000  |  0x1001  |  0x1002  |  0x1003  |
                +----------+----------+----------+----------+
Little:         |  01      |  00      |  00      |  00      |
                +----------+----------+----------+----------+
Big:            |  00      |  00      |  00      |  01      |
                +----------+----------+----------+----------+

Step #2  Cast the address to a char pointer (focuses on first byte)
                +----------+
Memory Address  |  0x1000  |
                +----------+
Little:         |  01      |
                +----------+
Big:            |  00      |
                +----------+

Step #3  Dereference the char pointer to get the value

Little:         Returns 1 (for little-endian)
Big:            Returns 0 (for big-endian)

Demo

各自安好 2024-08-25 03:31:59

如果 boost 可用,那么您可以使用 Boost.Predef 其中包含各种预定义的目标平台的宏,包括字节顺序 (BOOST_ENDIAN_*)。是的 boost 通常被认为是一个 C++ 库,但这是一个可以使用的预处理器标头C 也是如此!它允许您在编译时中便携式地检测字节序

该库从它可以收集的 C、C++、Objective C 和 Objective C++ 预定义宏或一般可用标头中定义的信息中定义了一组编译器、体系结构、操作系统、库和其他版本号。该库的想法源于一项扩展 Boost Config 库的提议,以提供比它支持的功能定义更多且一致的信息。以下是该简短提案的编辑版本。

例如,

#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/other/endian.h>

#if   BOOST_ENDIAN_BIG_BYTE
#elif BOOST_ENDIAN_LITTLE_BYTE
#elif BOOST_ENDIAN_LITTLE_WORD
...
#endif

更多详细信息可以在 BOOST_ENDIAN_* section

Demo on Godbolt


Note that it obviously can不检测可以在运行时期间更改字节序的双端平台

检测是保守的,因为它仅识别它确定知道的字节序。特别是,没有指示双字节序,因为除了操作系统提供的标头之外,实际上不可能从任何东西确定字节序。目前已知的标头并未定义程序化双字节序可用。

If boost is available then you can use Boost.Predef which contains various predefined macros for the target platform including endianness (BOOST_ENDIAN_*). Yes boost is often thought as a C++ library, but this one is a preprocessor header that works with C as well! It allows you to detect endian in compile time portably

This library defines a set of compiler, architecture, operating system, library, and other version numbers from the information it can gather of C, C++, Objective C, and Objective C++ predefined macros or those defined in generally available headers. The idea for this library grew out of a proposal to extend the Boost Config library to provide more, and consistent, information than the feature definitions it supports. What follows is an edited version of that brief proposal.

For example

#include <boost/predef.h>
// or just include the necessary header
// #include <boost/predef/other/endian.h>

#if   BOOST_ENDIAN_BIG_BYTE
#elif BOOST_ENDIAN_LITTLE_BYTE
#elif BOOST_ENDIAN_LITTLE_WORD
...
#endif

More details can be found in BOOST_ENDIAN_* section

Demo on Godbolt


Note that it obviously can't detect bi-endian platforms where the endian can be changed during runtime

The detection is conservative in that it only identifies endianness that it knows for certain. In particular bi-endianness is not indicated as is it not practically possible to determine the endianness from anything but an operating system provided header. And the currently known headers do not define that programatic bi-endianness is available.

梦境 2024-08-25 03:31:59

我的答案并不像所问的那样,但是找到您的系统是小端还是大端非常简单?

代码:

#include<stdio.h>

int main()
{
  int a = 1;
  char *b;

  b = (char *)&a;
  if (*b)
    printf("Little Endian\n");
  else
    printf("Big Endian\n");
}

My answer is not as asked but It is really simple to find if your system is little endian or big endian?

Code:

#include<stdio.h>

int main()
{
  int a = 1;
  char *b;

  b = (char *)&a;
  if (*b)
    printf("Little Endian\n");
  else
    printf("Big Endian\n");
}
情域 2024-08-25 03:31:59

用于检查系统是小字节序还是大字节序的 C 代码。

int i = 7;
char* pc = (char*)(&i);
if (pc[0] == '\x7') // aliasing through char is ok
    puts("This system is little-endian");
else
    puts("This system is big-endian");

C Code for checking whether a system is little-endian or big-indian.

int i = 7;
char* pc = (char*)(&i);
if (pc[0] == '\x7') // aliasing through char is ok
    puts("This system is little-endian");
else
    puts("This system is big-endian");
も让我眼熟你 2024-08-25 03:31:59

用于查找字节序

#define ENDIANNES() ((1 && 1 == 0) ? printf("Big-Endian"):printf("Little-Endian"))

的宏

#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}

int main(void) 
{
       ENDIAN();
       return 0;
}

Macro to find endiannes

#define ENDIANNES() ((1 && 1 == 0) ? printf("Big-Endian"):printf("Little-Endian"))

or

#include <stdio.h>

#define ENDIAN() { \
volatile unsigned long ul = 1;\
volatile unsigned char *p;\
p = (volatile unsigned char *)&ul;\
if (*p == 1)\
puts("Little endian.");\
else if (*(p+(sizeof(unsigned long)-1)) == 1)\
puts("Big endian.");\
else puts("Unknown endian.");\
}

int main(void) 
{
       ENDIAN();
       return 0;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文