C ++μμ λΉ μλμκ³Ό 리ν μλμ κ°μ μ΄λ»κ² λ³νν©λκΉ?
νΈμ§ : λͺ νμ±μ μν΄ μ΄μ§ λ°μ΄ν° (λ°°μ λ°λ λΆλ μμμ κ° λ° 32 λΉνΈ λ° 64 λΉνΈ μ μ)λ₯Ό ν CPU μν€ν μ²μμ λ€λ₯Έ CPU μν€ν μ²λ‘ λ³νν΄μΌν©λλ€. μ΄κ²μ λ€νΈμνΉκ³Ό κ΄λ ¨μ΄ μμΌλ―λ‘ ntoh () λ° μ΄μ μ μ¬ν ν¨μλ μ¬κΈ°μ μλνμ§ μμ΅λλ€.
νΈμ§ # 2 : λ΄κ° λ°μ λ€μΈ λλ΅μ λ΄κ° νκ²ν νλ μ»΄νμΌλ¬μ μ§μ μ μ©λ©λλ€ (κ·Έλμ λ΄κ° μ νν μ΄μ ). κ·Έλ¬λ μ¬κΈ°μλ λ§€μ° νλ₯νκ³ μ΄μμ±μ΄ μ’μ λ€λ₯Έ λ΅λ³μ΄ μμ΅λλ€.
λ΅λ³
λΉμ μ΄ μ¬μ©νλ κ²½μ° Visual C ++λ₯Ό λ€μμ μν : λΉμ μ λ€μκ³Ό κ°μ κΈ°λ₯μ intrin.h ν¬ν¨ μ ν :
16 λΉνΈ μ«μμ κ²½μ° :
unsigned short _byteswap_ushort(unsigned short value);
32 λΉνΈ μ«μμ κ²½μ° :
unsigned long _byteswap_ulong(unsigned long value);
64 λΉνΈ μ«μμ κ²½μ° :
unsigned __int64 _byteswap_uint64(unsigned __int64 value);
8 λΉνΈ μ«μ (λ¬Έμ)λ λ³ν ν νμκ° μμ΅λλ€.
λν μ΄λ€μ λΆνΈμλ μ μμ λν΄μλ§ μλν©λλ€.
float λ° doubleμ κ²½μ° νΈμ€νΈ μμ€ν μ λ°μ΄νΈ μμκ° μκ±°λ μμ μ μμΌλ―λ‘ μΌλ° μ μλ₯Ό μ¬μ©νλ κ²μ΄ λ μ΄λ ΅μ΅λλ€. λΉ μλμ λ¨Έμ μμ 리ν μλμ μλ λ₯Ό μ»μ μ μμΌλ©° κ·Έ λ°λλ κ°λ₯ν©λλ€.
λ€λ₯Έ μ»΄νμΌλ¬λ λΉμ·ν λ³Έμ§μ κ°μ§κ³ μμ΅λλ€.
μλ₯Ό λ€μ΄ GCC μμλ μ¬κΈ°μ μ€λͺ λλλ‘ μΌλΆ λ΄μ₯μ μ§μ νΈμΆ ν μ μμ΅λλ€ .
uint32_t __builtin_bswap32 (uint32_t x)
uint64_t __builtin_bswap64 (uint64_t x)
(무μμ ν¬ν¨ ν νμκ° μμ΅λλ€). Afaik bits.hλ gcc μ€μ¬μ΄ μλ λ°©μμΌλ‘ λμΌν ν¨μλ₯Ό μ μΈν©λλ€.
16 λΉνΈ μ€μμ λΉνΈ νμ μ λλ€.
λ‘€λ§ λμ λ΄μ₯ ν¨μλ₯Ό νΈμΆνλ©΄ μ΅μμ μ±λ₯κ³Ό μ½λ λ°λλ₯Ό μ»μ μ μμ΅λλ€.
λ΅λ³
κ°λ¨ν λ§ν΄μ:
#include <climits>
template <typename T>
T swap_endian(T u)
{
static_assert (CHAR_BIT == 8, "CHAR_BIT != 8");
union
{
T u;
unsigned char u8[sizeof(T)];
} source, dest;
source.u = u;
for (size_t k = 0; k < sizeof(T); k++)
dest.u8[k] = source.u8[sizeof(T) - k - 1];
return dest.u;
}
μ¬μ©λ² : swap_endian<uint32_t>(42)
.
λ΅λ³
μμ λ°μ΄νΈ μ£Όλ¬Έ μ°©μ€ λ‘ νμ΄ν¬μ μν΄ :
λ°μ΄ν° μ€νΈλ¦Όμ 리ν μλμ μΈμ½λ© λ 32 λΉνΈ μ μκ° μλ€κ³ κ°μ ν΄ λ΄ μλ€. λΆνΈμλ λ°μ΄νΈλ₯Ό κ°μ νμ¬ μΆμΆνλ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
i = (data[0]<<0) | (data[1]<<8) | (data[2]<<16) | (data[3]<<24);
λΉ μλμμ΄λΌλ©΄ μΆμΆ λ°©λ²μ λ€μκ³Ό κ°μ΅λλ€.
i = (data[3]<<0) | (data[2]<<8) | (data[1]<<16) | (data[0]<<24);
TL; DR : νλ«νΌ κΈ°λ³Έ μμμ λν΄ κ±±μ νμ§ λ§μμμ€ . μΉ΄μ΄νΈλ λͺ¨λ μ½κ³ μλ μ€νΈλ¦Όμ λ°μ΄νΈ μμμ΄λ©° μ μ μλμ΄ μκΈ°λ₯Ό λ°λλλ€.
μ°Έκ³ : μ£Όμμμ λͺ
μ μ μ ν λ³νμ΄μλ κ²μΌλ‘ μΈκΈλμμΌλ―λ‘ λλ data
μ λ°°μ΄μ΄μ΄μΌν©λλ€ . μ¬μ© λλ (μλͺ
κ²½μ°)κ° λ°μν©λλ€ μ μλ‘ μΉμ§νκ³ μ μ¬μ UBμ΄λ€ λΆνΈ λΉνΈμ 1μ μ΄λ.unsigned char
uint8_t
signed char
char
data[x]
data[x] << 24
λ΅λ³
λ€νΈμν¬ / νΈμ€νΈ νΈνμ±μ μν΄μ΄ μμ μ μννλ κ²½μ° λ€μμ μ¬μ©ν΄μΌν©λλ€.
ntohl() //Network to Host byte order (Long)
htonl() //Host to Network byte order (Long)
ntohs() //Network to Host byte order (Short)
htons() //Host to Network byte order (Short)
λ€λ₯Έ μ΄μ λ‘μ΄ μμ μ μννλ κ²½μ° μ¬κΈ°μ μ 곡λ byte_swap μ루μ μ€ νλκ° μ λλ‘ μλν©λλ€.
λ΅λ³
λλμ΄ κ²μλ¬Όμμ λͺ κ°μ§ μ μμνκ³ μ΄κ²μ ꡬμ±νκΈ° μν΄ ν¨κ» λͺ¨μμ΅λλ€.
#include <boost/type_traits.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/endian.hpp>
#include <stdexcept>
enum endianness
{
little_endian,
big_endian,
network_endian = big_endian,
#if defined(BOOST_LITTLE_ENDIAN)
host_endian = little_endian
#elif defined(BOOST_BIG_ENDIAN)
host_endian = big_endian
#else
#error "unable to determine system endianness"
#endif
};
namespace detail {
template<typename T, size_t sz>
struct swap_bytes
{
inline T operator()(T val)
{
throw std::out_of_range("data size");
}
};
template<typename T>
struct swap_bytes<T, 1>
{
inline T operator()(T val)
{
return val;
}
};
template<typename T>
struct swap_bytes<T, 2>
{
inline T operator()(T val)
{
return ((((val) >> 8) & 0xff) | (((val) & 0xff) << 8));
}
};
template<typename T>
struct swap_bytes<T, 4>
{
inline T operator()(T val)
{
return ((((val) & 0xff000000) >> 24) |
(((val) & 0x00ff0000) >> 8) |
(((val) & 0x0000ff00) << 8) |
(((val) & 0x000000ff) << 24));
}
};
template<>
struct swap_bytes<float, 4>
{
inline float operator()(float val)
{
uint32_t mem =swap_bytes<uint32_t, sizeof(uint32_t)>()(*(uint32_t*)&val);
return *(float*)&mem;
}
};
template<typename T>
struct swap_bytes<T, 8>
{
inline T operator()(T val)
{
return ((((val) & 0xff00000000000000ull) >> 56) |
(((val) & 0x00ff000000000000ull) >> 40) |
(((val) & 0x0000ff0000000000ull) >> 24) |
(((val) & 0x000000ff00000000ull) >> 8 ) |
(((val) & 0x00000000ff000000ull) << 8 ) |
(((val) & 0x0000000000ff0000ull) << 24) |
(((val) & 0x000000000000ff00ull) << 40) |
(((val) & 0x00000000000000ffull) << 56));
}
};
template<>
struct swap_bytes<double, 8>
{
inline double operator()(double val)
{
uint64_t mem =swap_bytes<uint64_t, sizeof(uint64_t)>()(*(uint64_t*)&val);
return *(double*)&mem;
}
};
template<endianness from, endianness to, class T>
struct do_byte_swap
{
inline T operator()(T value)
{
return swap_bytes<T, sizeof(T)>()(value);
}
};
// specialisations when attempting to swap to the same endianess
template<class T> struct do_byte_swap<little_endian, little_endian, T> { inline T operator()(T value) { return value; } };
template<class T> struct do_byte_swap<big_endian, big_endian, T> { inline T operator()(T value) { return value; } };
} // namespace detail
template<endianness from, endianness to, class T>
inline T byte_swap(T value)
{
// ensure the data is only 1, 2, 4 or 8 bytes
BOOST_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8);
// ensure we're only swapping arithmetic types
BOOST_STATIC_ASSERT(boost::is_arithmetic<T>::value);
return detail::do_byte_swap<from, to, T>()(value);
}
λ΅λ³
λΉ μλμμμ 리ν μλμμΌλ‘κ°λ μ μ°¨λ 리ν μλμμμ λΉ μλμμΌλ‘κ°λ μ μ°¨μ λμΌν©λλ€.
μμ μ½λλ λ€μκ³Ό κ°μ΅λλ€.
void swapByteOrder(unsigned short& us)
{
us = (us >> 8) |
(us << 8);
}
void swapByteOrder(unsigned int& ui)
{
ui = (ui >> 24) |
((ui<<8) & 0x00FF0000) |
((ui>>8) & 0x0000FF00) |
(ui << 24);
}
void swapByteOrder(unsigned long long& ull)
{
ull = (ull >> 56) |
((ull<<40) & 0x00FF000000000000) |
((ull<<24) & 0x0000FF0000000000) |
((ull<<8) & 0x000000FF00000000) |
((ull>>8) & 0x00000000FF000000) |
((ull>>24) & 0x0000000000FF0000) |
((ull>>40) & 0x000000000000FF00) |
(ull << 56);
}
λ΅λ³
BSWAPλΌλ 쑰립 λͺ λ Ήμ΄ μμΌλ©°, μ€μμ λ§€μ° λΉ λ₯΄κ² μν ν©λλ€. μ¬κΈ°μμ μ½μ μ μμ΅λλ€ .
Visual Studio λλλ³΄λ€ μ ννκ²λ Visual C ++ λ°νμ λΌμ΄λΈλ¬λ¦¬μλμ΄λ₯Όμν νλ«νΌ λ΄μ₯ κΈ°λ₯μ΄ _byteswap_ushort(), _byteswap_ulong(), and _byteswap_int64()
μμ΅λλ€. λ€λ₯Έ νλ«νΌμμλ λΉμ·ν΄μΌνμ§λ§ νλ«νΌμ΄ 무μμΈμ§ μμ§ λͺ»ν©λλ€.