C语言 在 C 中将大端转换为小端 [不使用提供的函数]
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2182002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
convert big endian to little endian in C [without using provided func]
提问by Alex Xander
I need to write a function to convert big endian to little endian in C. I can not use any library function.
我需要编写一个函数来在 C 中将大端转换为小端。我不能使用任何库函数。
回答by Sam Post
Assuming what you need is a simple byte swap, try something like
假设你需要的是一个简单的字节交换,试试像
Unsigned 16 bit conversion:
无符号 16 位转换:
swapped = (num>>8) | (num<<8);
Unsigned 32-bit conversion:
无符号 32 位转换:
swapped = ((num>>24)&0xff) | // move byte 3 to byte 0
((num<<8)&0xff0000) | // move byte 1 to byte 2
((num>>8)&0xff00) | // move byte 2 to byte 1
((num<<24)&0xff000000); // byte 0 to byte 3
This swaps the byte orders from positions 1234 to 4321. If your input was 0xdeadbeef, a 32-bit endian swap might have output of 0xefbeadde.
这0xdeadbeef会将字节顺序从位置 1234 交换到 4321。如果您的输入是,则 32 位字节序交换可能会输出0xefbeadde。
The code above should be cleaned up with macros or at least constants instead of magic numbers, but hopefully it helps as is
上面的代码应该用宏或至少是常量而不是幻数来清理,但希望它按原样提供帮助
EDIT: as another answer pointed out, there are platform, OS, and instruction set specific alternatives which can be MUCH faster than the above. In the Linux kernel there are macros (cpu_to_be32 for example) which handle endianness pretty nicely. But these alternatives are specific to their environments. In practice endianness is best dealt with using a blend of available approaches
编辑:正如另一个答案所指出的,有特定于平台、操作系统和指令集的替代方案,它们可以比上述方案快得多。在 Linux 内核中有宏(例如 cpu_to_be32)可以很好地处理字节序。但是这些替代方案是特定于它们的环境的。在实践中,最好使用可用方法的混合来处理字节序
回答by Amir Mgh
By including:
通过包括:
#include <byteswap.h>
you can get an optimized version of machine-dependent byte-swapping functions. Then, you can easily use the following functions:
您可以获得与机器相关的字节交换函数的优化版本。然后,您可以轻松使用以下功能:
__bswap_32 (uint32_t input)
or
或者
__bswap_16 (uint16_t input)
回答by chmike
#include <stdint.h>
//! Byte swap unsigned short
uint16_t swap_uint16( uint16_t val )
{
return (val << 8) | (val >> 8 );
}
//! Byte swap short
int16_t swap_int16( int16_t val )
{
return (val << 8) | ((val >> 8) & 0xFF);
}
//! Byte swap unsigned int
uint32_t swap_uint32( uint32_t val )
{
val = ((val << 8) & 0xFF00FF00 ) | ((val >> 8) & 0xFF00FF );
return (val << 16) | (val >> 16);
}
//! Byte swap int
int32_t swap_int32( int32_t val )
{
val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF );
return (val << 16) | ((val >> 16) & 0xFFFF);
}
Update: Added 64bit byte swapping
更新:添加了 64 位字节交换
int64_t swap_int64( int64_t val )
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | ((val >> 32) & 0xFFFFFFFFULL);
}
uint64_t swap_uint64( uint64_t val )
{
val = ((val << 8) & 0xFF00FF00FF00FF00ULL ) | ((val >> 8) & 0x00FF00FF00FF00FFULL );
val = ((val << 16) & 0xFFFF0000FFFF0000ULL ) | ((val >> 16) & 0x0000FFFF0000FFFFULL );
return (val << 32) | (val >> 32);
}
回答by Michael J
Here's a fairly generic version; I haven't compiled it, so there are probably typos, but you should get the idea,
这是一个相当通用的版本;我还没有编译它,所以可能有错别字,但你应该明白,
void SwapBytes(void *pv, size_t n)
{
assert(n > 0);
char *p = pv;
size_t lo, hi;
for(lo=0, hi=n-1; hi>lo; lo++, hi--)
{
char tmp=p[lo];
p[lo] = p[hi];
p[hi] = tmp;
}
}
#define SWAP(x) SwapBytes(&x, sizeof(x));
NB:This is notoptimised for speed or space. It is intended to be clear (easy to debug) and portable.
注意:这并未针对速度或空间进行优化。它旨在清晰(易于调试)和便携。
Update 2018-04-04Added the assert() to trap the invalid case of n == 0, as spotted by commenter @chux.
更新 2018-04-04添加了 assert() 以捕获 n == 0 的无效情况,正如评论者@chux 所发现的那样。
回答by kol
If you need macros (e.g. embedded system):
如果您需要宏(例如嵌入式系统):
#define SWAP_UINT16(x) (((x) >> 8) | ((x) << 8))
#define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24))
回答by Sam Harwell
Edit:These are library functions. Following them is the manual way to do it.
编辑:这些是库函数。按照他们是手动方式来做到这一点。
I am absolutely stunned by the number of people unaware of __byteswap_ushort, __byteswap_ulong, and __byteswap_uint64. Sure they are Visual C++ specific, but they compile down to some delicious code on x86/IA-64 architectures. :)
我对不知道__byteswap_ushort、__byteswap_ulong 和 __byteswap_uint64的人数感到非常震惊。当然它们是特定于 Visual C++ 的,但它们在 x86/IA-64 体系结构上编译成一些美味的代码。:)
Here's an explicit usage of the bswapinstruction, pulled from this page. Note that the intrinsic form above will alwaysbe faster than this, I only added it to give an answer without a library routine.
这是该bswap指令的显式用法,摘自此页面。请注意,上面的固有形式总是比这更快,我只是添加它来给出没有库例程的答案。
uint32 cq_ntohl(uint32 a) {
__asm{
mov eax, a;
bswap eax;
}
}
回答by dreamlax
As a joke:
开个玩笑:
#include <stdio.h>
int main (int argc, char *argv[])
{
size_t sizeofInt = sizeof (int);
int i;
union
{
int x;
char c[sizeof (int)];
} original, swapped;
original.x = 0x12345678;
for (i = 0; i < sizeofInt; i++)
swapped.c[sizeofInt - i - 1] = original.c[i];
fprintf (stderr, "%x\n", swapped.x);
return 0;
}
回答by jcomeau_ictx
here's a way using the SSSE3 instruction pshufb using its Intel intrinsic, assuming you have a multiple of 4 ints:
这是一种使用 SSSE3 指令 pshufb 使用其 Intel 内在函数的方法,假设您有 4int的倍数:
unsigned int *bswap(unsigned int *destination, unsigned int *source, int length) {
int i;
__m128i mask = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
for (i = 0; i < length; i += 4) {
_mm_storeu_si128((__m128i *)&destination[i],
_mm_shuffle_epi8(_mm_loadu_si128((__m128i *)&source[i]), mask));
}
return destination;
}
回答by Paul
Will this work / be faster?
这会工作/更快吗?
uint32_t swapped, result;
((byte*)&swapped)[0] = ((byte*)&result)[3];
((byte*)&swapped)[1] = ((byte*)&result)[2];
((byte*)&swapped)[2] = ((byte*)&result)[1];
((byte*)&swapped)[3] = ((byte*)&result)[0];
回答by Patrick Schlüter
EDIT: This function only swaps the endianness of aligned 16 bit words. A function often necessary for UTF-16/UCS-2 encodings. EDIT END.
编辑:此函数仅交换对齐的 16 位字的字节序。UTF-16/UCS-2 编码通常需要的函数。编辑结束。
If you want to change the endianess of a memory block you can use my blazingly fast approach. Your memory array should have a size that is a multiple of 8.
如果你想改变内存块的字节序,你可以使用我极快的方法。您的内存阵列的大小应该是 8 的倍数。
#include <stddef.h>
#include <limits.h>
#include <stdint.h>
void ChangeMemEndianness(uint64_t *mem, size_t size)
{
uint64_t m1 = 0xFF00FF00FF00FF00ULL, m2 = m1 >> CHAR_BIT;
size = (size + (sizeof (uint64_t) - 1)) / sizeof (uint64_t);
for(; size; size--, mem++)
*mem = ((*mem & m1) >> CHAR_BIT) | ((*mem & m2) << CHAR_BIT);
}
This kind of function is useful for changing the endianess of Unicode UCS-2/UTF-16 files.
这种函数对于改变 Unicode UCS-2/UTF-16 文件的字节顺序很有用。

