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()
์์ต๋๋ค. ๋ค๋ฅธ ํ๋ซํผ์์๋ ๋น์ทํด์ผํ์ง๋ง ํ๋ซํผ์ด ๋ฌด์์ธ์ง ์์ง ๋ชปํฉ๋๋ค.