Endian使用C ++进行交换;请评论 [英] Endian swaps with C++; comments please

查看:61
本文介绍了Endian使用C ++进行交换;请评论的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

/ **

*样本用法:

* unsigned long longvar = 0x12345678;

* unsigned long be_longvar = endian :: host_to_big (longvar);

* unsigned short shortvar = 0x1234;

* unsigned short le_shortvar = endian :: host_to_little(shortvar);

* /


//对于std :: reverse:

#include< algorithm>

#include< limits>


//关于字节序信息:

#include< endian.h>

// Linux使用__BYTE_ORDER

// FreeBSD和Apple / Darwin使用_BYTE_ORDER

//其他一些BSD变种使用BYTE_ORDER

#if(定义__BYTE_ORDER&& __BYTE_ORDER == __ BIG_ENDIAN) || \

(定义_BYTE_ORDER&& _BYTE_ORDER == _BIG_ENDIAN)|| \

(定义为BYTE_ORDER&& BYTE_ORDER == BIG_ENDIAN)

#define IS_BIG_ENDIAN 1

#else

#define IS_BIG_ENDIAN 0

#endif


命名空间字节序{


//此函数将复制提供的值并返回一个字节交换的

//版本。必要时,可以/应该针对特定的

//体系结构优化此功能。可能还需要为某些类型创建

//部分特化,因为此函数的当前状态仅允许交换某些基本类型。 br />
模板< typename _type>

_type byteswap(_type val){

if(std :: numeric_limits< _type> :: is_specialized& &

!std :: numeric_limits< _type> :: is_signed){

//找到一个专门的类型且未签名的类型。

开关(sizeof(_type)){

案例1:

返回val;

案例2:

return((val& 0x00ff)<< 8)| ((val& 0xff00)>> 8);

案例4:

return((val& 0x000000ff)<< 24)| ((val& 0x0000ff00)<< 8)|

((val& 0x00ff0000)>> 8)| ((val& 0xff000000)>> 24);

}

}

//使用不同的/回退交换此类型/ hacky方法:

unsigned char * v = reinterpret_cast< unsigned char *>(& val);

std :: reverse(v,v + sizeof(_type) ));

返回val;

}


模板< typename _type>

_type host_to_big(_type val){

返回IS_BIG_ENDIAN? val:byteswap(val);

}


模板< typename _type>

_type host_to_little(_type val){

返回IS_BIG_ENDIAN? byteswap(val):val;

}


模板< typename _type>

_type big_to_host(_type val){

返回IS_BIG_ENDIAN? val:byteswap(val);

}


模板< typename _type>

_type little_to_host(_type val){

返回IS_BIG_ENDIAN? byteswap(val):val;

}


} //结束名称空间结尾


// Don'不再需要这个定义了:

#undef IS_BIG_ENDIAN

/**
* Sample usage:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian::host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian::host_to_little(shortvar);
*/

// for std::reverse:
#include <algorithm>
#include <limits>

// for endian information:
#include <endian.h>
// Linux uses __BYTE_ORDER
// FreeBSD and Apple/Darwin use _BYTE_ORDER
// Some other BSD variants use BYTE_ORDER
#if (defined __BYTE_ORDER && __BYTE_ORDER==__BIG_ENDIAN) || \
(defined _BYTE_ORDER && _BYTE_ORDER== _BIG_ENDIAN) || \
(defined BYTE_ORDER && BYTE_ORDER== BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#else
#define IS_BIG_ENDIAN 0
#endif

namespace endian {

// This function will copy the supplied value and return a byte-swapped
// version of it. This function may/should be optimized for specific
// architectures when necessary. It may also be necessary to create
// partial specializations for certain types, since the current state
// of this function only allows some fundamental types to be swapped.
template <typename _type>
_type byteswap(_type val) {
if (std::numeric_limits<_type>::is_specialized &&
!std::numeric_limits<_type>::is_signed) {
// Found a type that is specialized and is unsigned.
switch (sizeof(_type)) {
case 1:
return val;
case 2:
return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
case 4:
return ((val & 0x000000ff) << 24) | ((val & 0x0000ff00) << 8) |
((val & 0x00ff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
// Swap this type using a different/fallback/hacky method:
unsigned char* v = reinterpret_cast<unsigned char*>(&val);
std::reverse(v, v + sizeof(_type));
return val;
}

template <typename _type>
_type host_to_big(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}

template <typename _type>
_type host_to_little(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}

template <typename _type>
_type big_to_host(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}

template <typename _type>
_type little_to_host(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}

} // end namespace endian

// Don''t need this definition anymore:
#undef IS_BIG_ENDIAN

推荐答案



Aaron Graham <在****** @ gmail.com>在消息中写道

news:11 ********************** @ g49g2000cwa.googlegr oups.com ...

"Aaron Graham" <at******@gmail.com> wrote in message
news:11**********************@g49g2000cwa.googlegr oups.com...
/ **
*样本用法:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian :: host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian :: host_to_little(shortvar);
* /
/**
* Sample usage:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian::host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian::host_to_little(shortvar);
*/




我从未见过需要交换实际的整数变量值。我执行任何交换代码时唯一的

时间是我写出一个整数类型的

变量到磁盘(或读回来),当这些数据可能时阅读

另一个平台。我们决定了文件中所有整数的标准,

并且所有平台都必须以这种格式编写(和读取)。


所以,在每个平台上,我们有数字数据读取和写入功能

类型,按照我们需要的顺序输入/输出数据。


在Mac上,例如,读写函数只是从第一个内存位置读取/写入

字节到最后,而在Windows上,我们以相反的顺序读/写
字节。


这样,内存中永远不存储数值变量(除了

可能在缓冲区中),我们不得不担心字节顺序 。


-Howard



I''ve never seen a need to swap actual integer variable values. The only
time I execute any swapping code is when I''m writing out an integer-type
variable to disk (or reading it back), when that data might be read on
another platform. We decided on a standard for all integers in the files,
and all platforms must write (and read) in that format.

So, on each platform, we have read and write functions for the numeric data
types, which stream in/out the data in the order we need.

On the Mac, for example, the read and write functions simply read/write the
bytes from first memory location to last, while on Windows, we read/write
the bytes in reverse order.

This way, there''s never a stored numeric variable in memory (aside from
perhaps in a buffer), which we have to worry about the "endianness" of.

-Howard


Aaron Graham写道:
Aaron Graham wrote:
[...]
switch(sizeof(_type)){
案例1:
返回val;
案例2:
return((val& 0x00ff)<< 8)| ((val& 0xff00)>> 8);


这假定''sizeof''返回八位字节的数量。它没有。

它返回''字节''的数量。请阅读差异。

案例4:
返回((val& 0x000000ff)<< 24)| ((val& 0x0000ff00)<< 8)|
((val& 0x00ff0000)>> 8)| ((val& 0xff000000)>> 24);
}
}
[..]
[...]
switch (sizeof(_type)) {
case 1:
return val;
case 2:
return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
This assumes that ''sizeof'' returns the number of octets. It doesn''t.
It returns the number of ''bytes''. Please read up on the difference.
case 4:
return ((val & 0x000000ff) << 24) | ((val & 0x0000ff00) << 8) |
((val & 0x00ff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
[..]




V



V


你好,


看看:


man htonl

(网络字节顺序为bigendian)

hello,

have a look at:

man htonl

("network" byte order is bigendian)

/ **
*样本用法:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian :: host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian :: host_to_little(shortvar );
* /

//对于std :: reverse:
#include< algorithm>
#include< limits>

//对于endian信息:
#include< endian.h>
// Linux使用__BYTE_ORDER
// FreeBSD和Apple / Darwin使用_BYTE_ORDER
//其他BSD变体使用BYTE_ORDER
#if(已定义__BYTE_ORDER&& __BYTE_ORDER == __ BIG_ENDIAN)|| \
(已定义_BYTE_ORDER&& _BYTE_ORDER == _BIG_ENDIAN)|| \
(定义为BYTE_ORDER&& BYTE_ORDER == BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#else
#define IS_BIG_ENDIAN 0
#endif

命名空间endian {

//这个函数将复制提供的值并返回一个字节交换的
//版本。在必要时,可以/应该针对特定的架构优化此功能。可能还需要为某些类型创建
//部分特化,因为此函数的当前状态仅允许交换某些基本类型。
template< typename _type> ;
_type byteswap(_type val){
if(std :: numeric_limits< _type> :: is_specialized&&
!std :: numeric_limits< _type> :: is_signed){
//找到一个专门的类型并且是无符号的。
switch(sizeof(_type)){
案例1:
返回val;
案例2:
return((val& 0x00ff)<< 8)| ((val& 0xff00)>> 8);
案例4:
return((val& 0x000000ff)<< 24)| ((val& 0x0000ff00)<< 8)|
((val& 0x00ff0000)>> 8)| ((val& 0xff000000)>> 24);
}
} //使用不同的/ fallback / hacky方法交换此类型:
unsigned char * v = reinterpret_cast< unsigned char *>(& val);
std :: reverse(v,v + sizeof(_type));
返回val;
}

模板< typename _type>
_type host_to_big(_type val){
返回IS_BIG_ENDIAN? val:byteswap(val);
}

模板< typename _type>
_type host_to_little(_type val){
返回IS_BIG_ENDIAN? byteswap(val):val;
}

模板< typename _type>
_type big_to_host(_type val){
返回IS_BIG_ENDIAN? val:byteswap(val);
}

模板< typename _type>
_type little_to_host(_type val){
返回IS_BIG_ENDIAN? byteswap(val):val;
}
} // end namespace endian

//不再需要这个定义了:
# undef IS_BIG_ENDIAN
/**
* Sample usage:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian::host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian::host_to_little(shortvar);
*/

// for std::reverse:
#include <algorithm>
#include <limits>

// for endian information:
#include <endian.h>
// Linux uses __BYTE_ORDER
// FreeBSD and Apple/Darwin use _BYTE_ORDER
// Some other BSD variants use BYTE_ORDER
#if (defined __BYTE_ORDER && __BYTE_ORDER==__BIG_ENDIAN) || \
(defined _BYTE_ORDER && _BYTE_ORDER== _BIG_ENDIAN) || \
(defined BYTE_ORDER && BYTE_ORDER== BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#else
#define IS_BIG_ENDIAN 0
#endif

namespace endian {

// This function will copy the supplied value and return a byte-swapped
// version of it. This function may/should be optimized for specific
// architectures when necessary. It may also be necessary to create
// partial specializations for certain types, since the current state
// of this function only allows some fundamental types to be swapped.
template <typename _type>
_type byteswap(_type val) {
if (std::numeric_limits<_type>::is_specialized &&
!std::numeric_limits<_type>::is_signed) {
// Found a type that is specialized and is unsigned.
switch (sizeof(_type)) {
case 1:
return val;
case 2:
return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
case 4:
return ((val & 0x000000ff) << 24) | ((val & 0x0000ff00) << 8) |
((val & 0x00ff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
// Swap this type using a different/fallback/hacky method:
unsigned char* v = reinterpret_cast<unsigned char*>(&val);
std::reverse(v, v + sizeof(_type));
return val;
}

template <typename _type>
_type host_to_big(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}

template <typename _type>
_type host_to_little(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}

template <typename _type>
_type big_to_host(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}

template <typename _type>
_type little_to_host(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}

} // end namespace endian

// Don''t need this definition anymore:
#undef IS_BIG_ENDIAN



这篇关于Endian使用C ++进行交换;请评论的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆