C++ htonll and back
C++ htonll and back
我发现下面的代码能够将int64_t转换为网络字节顺序。现在我需要相反的代码,这样网络字节顺序被转换回我的小端序机器。代码是这样的。
int64_t decode(void* value){
int64_t vv = *((int64_t*) value);
int num = 42;
if(*(char *)&num == 42) //test big/little endian
return (((uint64)htonl(vv)) << 32) + htonl(vv >> 32);
else
return vv;
}
非常感谢!
您的htonll
的代码
#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl((x) >> 32))
将字节端到端翻转。如果应用它两次,它将值恢复到原始状态。因此,同样的函数可以用于ntohll
。
htonl
可通过以下步骤完成
- 如果它的大端系统直接返回值。不需要做任何转换。如果是小端系统,需要做下面的转换。
- 取LSB 32位并应用'htonl'和shift 32次。
- 采取MSB 32位(通过将uint64_t值右移32倍)并应用'htonl'
- 现在对第二步和第三步收到的值应用位或。
对于ntohll
同样
#define HTONLL(x) ((1==htonl(1)) ? (x) : (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32)))
#define NTOHLL(x) ((1==ntohl(1)) ? (x) : (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32)))
在c++中23日std::byteswap
,例如:
#include <bit>
#include <cstdint>
auto htonll(std::uint64_t h)
{
return (std::endian::native == std::endian::big) ? h : std::byteswap(h);
}
在此之前,此解决方案将适用于常量表达式:
#include <cstdint>
#include <climits>
#include <bit>
constexpr auto htonll(std::uint64_t h)
{
if (std::endian::native != std::endian::big) {
static_assert(CHAR_BIT==8);
constexpr auto shift_bytes1{8};
constexpr auto shift_bytes2{16};
constexpr auto shift_bytes4{32};
h = ((h&UINT64_C(0x00FF00FF00FF00FF))<<shift_bytes1) | ((h&UINT64_C(0xFF00FF00FF00FF00))>>shift_bytes1);
h = ((h&UINT64_C(0x0000FFFF0000FFFF))<<shift_bytes2) | ((h&UINT64_C(0xFFFF0000FFFF0000))>>shift_bytes2);
h = ((h&UINT64_C(0x00000000FFFFFFFF))<<shift_bytes4) | ((h&UINT64_C(0xFFFFFFFF00000000))>>shift_bytes4);
}
return h;
}
下面是我使用联合的方法。位移位方法也可以很好地工作,但恕我直言,要正确使用它有点棘手。
#include<stdlib.h>
#include<stdio.h>
union MyUnion {
int64_t i64;
int32_t i32[2];
};
int64_t htonll(int64_t hostFormatInt64)
{
MyUnion u;
u.i64 = hostFormatInt64;
int32_t temp = u.i32[0];
u.i32[0] = htonl(u.i32[1]);
u.i32[1] = htonl(temp);
return u.i64;
}
int64_t ntohll(int64_t networkFormatInt64)
{
MyUnion u;
u.i64 = networkFormatInt64;
int32_t temp = u.i32[0];
u.i32[0] = ntohl(u.i32[1]);
u.i32[1] = ntohl(temp);
return u.i64;
}
void Test(int64_t i)
{
printf("Testing value %llin", i);
int64_t networkI = htonll(i);
printf(" Network format is %lli (0x%llx)n", networkI, networkI);
int64_t hostAgainI = ntohll(networkI);
printf(" Back to host again %lli (0x%llx)n", hostAgainI, hostAgainI);
if (hostAgainI != i)
{
printf("ERROR, we didn't get the original value back!n");
abort();
}
}
int main()
{
// A quick unit test to make sure I didn't mess anything up :)
int64_t i = 0;
while(1)
{
Test(i);
Test(-i);
i += rand();
}
return 0;
}
复制自c:Program Files (x86)Windows Kits8.1IncludeumWinSock2.h
#if !defined(NO_EXTRA_HTON_FUNCTIONS) && !defined(__midl) && (defined(INCL_EXTRA_HTON_FUNCTIONS) || NTDDI_VERSION>=NTDDI_WIN8)
/*
* Byte order conversion functions for 64-bit integers and 32 + 64 bit
* floating-point numbers. IEEE big-endian format is used for the
* network floating point format.
*/
#define _WS2_32_WINSOCK_SWAP_LONG(l)
( ( ((l) >> 24) & 0x000000FFL ) |
( ((l) >> 8) & 0x0000FF00L ) |
( ((l) << 8) & 0x00FF0000L ) |
( ((l) << 24) & 0xFF000000L ) )
#define _WS2_32_WINSOCK_SWAP_LONGLONG(l)
( ( ((l) >> 56) & 0x00000000000000FFLL ) |
( ((l) >> 40) & 0x000000000000FF00LL ) |
( ((l) >> 24) & 0x0000000000FF0000LL ) |
( ((l) >> 8) & 0x00000000FF000000LL ) |
( ((l) << 8) & 0x000000FF00000000LL ) |
( ((l) << 24) & 0x0000FF0000000000LL ) |
( ((l) << 40) & 0x00FF000000000000LL ) |
( ((l) << 56) & 0xFF00000000000000LL ) )
#ifndef htonll
__inline unsigned __int64 htonll ( unsigned __int64 Value )
{
const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
return Retval;
}
#endif /* htonll */
#ifndef ntohll
__inline unsigned __int64 ntohll ( unsigned __int64 Value )
{
const unsigned __int64 Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
return Retval;
}
#endif /* ntohll */
#ifndef htonf
__inline unsigned __int32 htonf ( float Value )
{
unsigned __int32 Tempval;
unsigned __int32 Retval;
Tempval = *(unsigned __int32*)(&Value);
Retval = _WS2_32_WINSOCK_SWAP_LONG (Tempval);
return Retval;
}
#endif /* htonf */
#ifndef ntohf
__inline float ntohf ( unsigned __int32 Value )
{
const unsigned __int32 Tempval = _WS2_32_WINSOCK_SWAP_LONG (Value);
float Retval;
*((unsigned __int32*)&Retval) = Tempval;
return Retval;
}
#endif /* ntohf */
#ifndef htond
__inline unsigned __int64 htond ( double Value )
{
unsigned __int64 Tempval;
unsigned __int64 Retval;
Tempval = *(unsigned __int64*)(&Value);
Retval = _WS2_32_WINSOCK_SWAP_LONGLONG (Tempval);
return Retval;
}
#endif /* htond */
#ifndef ntohd
__inline double ntohd ( unsigned __int64 Value )
{
const unsigned __int64 Tempval = _WS2_32_WINSOCK_SWAP_LONGLONG (Value);
double Retval;
*((unsigned __int64*)&Retval) = Tempval;
return Retval;
}
#endif /* ntohd */
#endif /* NO_EXTRA_HTON_FUNCTIONS */
使用Microsoft Visual Studio Professional 2015
版本14.0.25420.01更新3
Microsoft .NET Framework
版本4.7.03062
测试代码:
#include "stdafx.h"
#include <string>
#include <stdexcept>
#include <Shlwapi.h>
#pragma comment(lib, "shlwapi.lib")
int _getcharIfNeeded() {
HWND consoleWnd = GetConsoleWindow();
DWORD dwProcessId;
GetWindowThreadProcessId(consoleWnd, &dwProcessId);
if (GetCurrentProcessId() == dwProcessId)
{
printf("I have my own console, press enter to exitn");
return getchar();
}
else
{
return printf("This Console is not mine, good byen");
}
}
#include <boost/algorithm/hex.hpp>
#include <boost/format.hpp>
#include <boost/format/group.hpp>
int wmain(int argc, wchar_t *argv[])
{
#define SMB_FILE_SEPARATOR_CHAR ''
#define OWNER_FILE_PREFIX "~$"
std::string strFileName("\\10.23.57.72\fromw12r2\behavior\~$tree file-editing prohibited.xlsx");
const size_t posFileName = strFileName.find_last_of(SMB_FILE_SEPARATOR_CHAR);
bool isOwnerFile = std::string::npos != posFileName ? 0 == strncmp(strFileName.c_str() + posFileName + 1, OWNER_FILE_PREFIX, strlen(OWNER_FILE_PREFIX)) : false;
//https://stackoverflow.com/questions/16375340/c-htonll-and-back
//#define htonll(x) ((((uint64_t)htonl(x)) << 32) + htonl((x) >> 32))
#define HTONLL(x) ((1==htonl(1)) ? (x) : (((uint64_t)htonl((x) & 0xFFFFFFFFUL)) << 32) | htonl((uint32_t)((x) >> 32)))
#define NTOHLL(x) ((1==ntohl(1)) ? (x) : (((uint64_t)ntohl((x) & 0xFFFFFFFFUL)) << 32) | ntohl((uint32_t)((x) >> 32)))
const char smb2_sesid_bytes[] = { 0x23, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00 };
const uint64_t sessionId_reinterpret_bytes_in_host_order = *reinterpret_cast<const uint64_t*>(smb2_sesid_bytes);
const uint64_t sessionId_in_network_order = htonll(sessionId_reinterpret_bytes_in_host_order);
const std::string strHex = boost::algorithm::hex(std::string(reinterpret_cast<const char*>(&sessionId_in_network_order), sizeof(uint64_t)));
std::ostringstream strSink;
//https://en.cppreference.com/w/cpp/iterator/ostreambuf_iterator
boost::algorithm::hex(std::cbegin(smb2_sesid_bytes), std::cend(smb2_sesid_bytes), std::ostreambuf_iterator<char>(strSink));
printf(strSink.str().c_str());//std::cout << stream.str();
printOptimizedComparison();
std::stringstream stream; // #include <sstream> for this
const int MaximalAccess = 0x001f01ff;
//boost::io::group(hex, showbase, 40); //using boost::io::group;
stream << boost::format("PID=%1% (%1$#08x), MaximalAccess=%2% (%2$#08x), 0x%3$08xn") % GetCurrentProcessId() % MaximalAccess % 0x001f01ff;
stream << boost::format("%08xn") % MaximalAccess;
printf(stream.str().c_str());//std::cout << stream.str();
testRomanToInt("III", 3);
testRomanToInt("IV", 4);
testRomanToInt("IX", 9);
testRomanToInt("LVIII", 58);
testRomanToInt("MCMXCIV", 1994);
//https://stackoverflow.com/questions/663449/what-is-the-best-way-to-attach-a-debugger-to-a-process-in-vc-at-just-the-right
#ifdef __DEBUG
__debugbreak(); //__asm int 3
#endif
//it should just silently wait until you attach your debugger to the process.
//while (!::IsDebuggerPresent()) ::Sleep(100); // to avoid 100% CPU load
return _getcharIfNeeded(); //return IsDebuggerPresent() && getchar();
}
相关文章:
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- 推导 std::vector::back() 的返回类型
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- std::visit and std::variant usage
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- python ctypes and C++ pointers
- C++ htonll and back