Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将一个值从主机字节顺序转换为小端字节?_C++_C_Endianness - Fatal编程技术网

C++ 如何将一个值从主机字节顺序转换为小端字节?

C++ 如何将一个值从主机字节顺序转换为小端字节?,c++,c,endianness,C++,C,Endianness,我需要将一个短值从主机字节顺序转换为小端。如果目标是big-endian,我可以使用htons()函数,但可惜不是这样 我想我可以做到: swap(htons(val)) 但这可能会导致字节交换两次,结果正确,但会给我带来性能损失,这在我的情况下是不正确的。那么你应该知道你的endianness并有条件地调用htons()。实际上,甚至不是hton,而是有条件地交换字节。当然是编译时。这个技巧应该是:在启动时,使用带有伪值的ntohs,然后将结果值与原始值进行比较。如果两个值相同,则机器使用b

我需要将一个短值从主机字节顺序转换为小端。如果目标是big-endian,我可以使用htons()函数,但可惜不是这样

我想我可以做到:

swap(htons(val))

但这可能会导致字节交换两次,结果正确,但会给我带来性能损失,这在我的情况下是不正确的。

那么你应该知道你的endianness并有条件地调用htons()。实际上,甚至不是hton,而是有条件地交换字节。当然是编译时。

这个技巧应该是:在启动时,使用带有伪值的
ntohs
,然后将结果值与原始值进行比较。如果两个值相同,则机器使用big-endian,否则使用little-endian

然后,根据初始测试的结果,使用不执行任何操作或调用
ntohs
ToLittleEndian
方法


(根据评论中提供的信息编辑)

以下是一篇关于endianness以及如何从IBM确定endianness的文章:

它包含了一个如何在运行时确定endianness的示例(您只需要执行一次)

本页还有一节介绍反转字节顺序的方法:

short reverseShort (short s) {
    unsigned char c1, c2;

    if (is_bigendian()) {
        return s;
    } else {
        c1 = s & 255;
        c2 = (s >> 8) & 255;

        return (c1 << 8) + c2;
    }
}

我的经验法则性能猜测是,这取决于您是一次完成一大块数据的小端化,还是仅一个值:

如果只有一个值,那么函数调用开销可能会淹没不必要的字节交换开销,即使编译器没有优化不必要的字节交换。然后,您可能要将该值写入套接字连接的端口号,并尝试打开或绑定套接字,这与任何类型的位操作相比都需要一段时间。所以别担心

如果是一个大的块,那么您可能会担心编译器无法处理它。因此,请这样做:

if (!is_little_endian()) {
    for (int i = 0; i < size; ++i) {
        vals[i] = swap_short(vals[i]);
    }
}
#include <assert.h>
#include <limits.h>
#include <stdint.h>

void check_bits_per_byte(void)
{ assert(CHAR_BIT == 8); }

void check_sizeof_uint32(void)
{ assert(sizeof (uint32_t) == 4); }

void check_byte_order(void)
{
    static const union { unsigned char bytes[4]; uint32_t value; } byte_order =
        { { 1, 2, 3, 4 } };

    static const uint32_t little_endian = 0x04030201ul;
    static const uint32_t big_endian = 0x01020304ul;

    #ifdef LITTLE_ENDIAN
    assert(byte_order.value == little_endian);
    #endif

    #ifdef BIG_ENDIAN
    assert(byte_order.value == big_endian);
    #endif

    #if !defined LITTLE_ENDIAN && !defined BIG_ENDIAN
    assert(!"byte order unknown or unsupported");
    #endif
}

int main(void)
{
    check_bits_per_byte();
    check_sizeof_uint32();
    check_byte_order();
}
if(!is_little_endian()){
对于(int i=0;i
或者查看您的体系结构上的SIMD指令,这些指令可以更快地完成任务

Write
是一种使用任何你喜欢的技巧的小方法。我认为Robert S.Barnes提供的是可靠的,但由于您通常知道给定目标的大小,可能您应该有一个特定于平台的头文件,该头文件将其定义为一个计算为1或0的宏


与往常一样,如果您真的关心性能,那么请查看生成的程序集,以查看是否删除了无意义的代码,并对各种备选方案进行比较,以查看实际运行最快的部分。

类似于以下内容:

unsigned short swaps( unsigned short val)
{
    return ((val & 0xff) << 8) | ((val & 0xff00) >> 8);
}

/* host to little endian */

#define PLATFORM_IS_BIG_ENDIAN 1
#if PLATFORM_IS_LITTLE_ENDIAN
unsigned short htoles( unsigned short val)
{
    /* no-op on a little endian platform */
    return val;
}
#elif PLATFORM_IS_BIG_ENDIAN
unsigned short htoles( unsigned short val)
{
    /* need to swap bytes on a big endian platform */
    return swaps( val);
}
#else
unsigned short htoles( unsigned short val)
{
    /* the platform hasn't been properly configured for the */
    /* preprocessor to know if it's little or big endian    */

    /* use potentially less-performant, but always works option */

    return swaps( htons(val));
}
#endif
unsigned short swap(unsigned short val)
{
返回((val&0xff)>8);
}
/*小恩迪安的主人*/
#定义平台\u是\u BIG\u ENDIAN 1
#如果平台是小的
无符号短值(无符号短值)
{
/*在小endian平台上没有操作*/
返回val;
}
#如果平台是大的
无符号短值(无符号短值)
{
/*需要在big-endian平台上交换字节*/
收益互换(val);
}
#否则
无符号短值(无符号短值)
{
/*尚未正确配置平台以用于*/
/*预处理器,以了解它是小端还是大端*/
/*使用性能可能较低但始终有效的选项*/
收益互换(htons(val));
}
#恩迪夫
如果您有一个正确配置的系统(这样预处理器就知道目标id是little还是big-endian),您将得到一个“优化”版本的
htoles()
。否则,您将获得依赖于
htons()
的潜在非优化版本。无论如何,你会得到一些有用的东西

没有什么太棘手的东西,或多或少都是便携的

当然,您可以通过使用
inline
或您认为合适的宏来实现这一点,从而进一步提高优化的可能性


您可能想看看“可移植开源工具(POSH)”之类的实际实现,它定义了各种编译器的endianness。注意,访问库需要通过一个伪身份验证页面(尽管您不需要注册来提供任何个人详细信息):

不幸的是,使用标准C在编译时并没有真正的跨平台方法来确定系统的字节顺序。我建议在
config.h
中添加一个
\define
(或您或您的构建系统用于构建配置的任何其他内容)

检查
LITTLE\u ENDIAN
BIG\u ENDIAN
的正确定义的单元测试可能如下所示:

if (!is_little_endian()) {
    for (int i = 0; i < size; ++i) {
        vals[i] = swap_short(vals[i]);
    }
}
#include <assert.h>
#include <limits.h>
#include <stdint.h>

void check_bits_per_byte(void)
{ assert(CHAR_BIT == 8); }

void check_sizeof_uint32(void)
{ assert(sizeof (uint32_t) == 4); }

void check_byte_order(void)
{
    static const union { unsigned char bytes[4]; uint32_t value; } byte_order =
        { { 1, 2, 3, 4 } };

    static const uint32_t little_endian = 0x04030201ul;
    static const uint32_t big_endian = 0x01020304ul;

    #ifdef LITTLE_ENDIAN
    assert(byte_order.value == little_endian);
    #endif

    #ifdef BIG_ENDIAN
    assert(byte_order.value == big_endian);
    #endif

    #if !defined LITTLE_ENDIAN && !defined BIG_ENDIAN
    assert(!"byte order unknown or unsupported");
    #endif
}

int main(void)
{
    check_bits_per_byte();
    check_sizeof_uint32();
    check_byte_order();
}
#包括
#包括
#包括
每字节无效校验位(无效)
{断言(字符位==8);}
无效检查单元32的大小(无效)
{assert(sizeof(uint32_t)==4);}
无效检查字节顺序(无效)
{
静态常量并集{无符号字符字节[4];uint32\u t值;}字节顺序=
{ { 1, 2, 3, 4 } };
静态常数32_u t little_endian=0x04030201ul;
静态常数uint32\u t big\u endian=0x01020304ul;
#伊夫迪夫·小恩迪安
断言(byte_order.value==little_endian);
#恩迪夫
#伊夫德夫比昂
断言(byte_order.value==big_endian);
#恩迪夫
#如果!定义的小端点&!定义的大端点&
断言(!“字节顺序未知或不受支持”);
#恩迪夫
}
内部主(空)
{
检查每个字节的位();
检查_uint32()的大小;
检查字节顺序();
}

在许多Linux系统上,有一个带有转换功能的

您注意到OP担心性能损失吗?;-)OP只需要在启动时执行一次此检查。flyfishr64,每次检查结果。永远不要把编译时可以做的事情推迟到运行时。如果你对表演感到汗流浃背,#ifdef是你在这里的朋友。不要担心per