嗯,我一直在玩弄安东尼奥的答案,因为它感觉不完整和正确,最后我得到了比我预期的更复杂的东西,但复杂性有时有它的目的。
以下代码还手动执行htonl
/ ntohl
-like 转换(可能是相反的字节序,因此不希望将其与 混合htonl
,使用 this 或重写它htonl
)。
与 Antonio 的源不同,当输入数字类型为 8 字节长(unsigned long
在我的测试平台上是 8 字节- 顺便说一句,试试看?!)时,它不会覆盖内存,而是截断该值以适应所需的网络 char* 缓冲区。
我试图对其进行广泛评论,以便为您提供每个决定背后的想法,以增加进一步的复杂性(基本上使用unsigned int number
used as (char *)(&number)
,它也提供,但不保护字节顺序,如果您混合不同的长度类型,可能会以覆盖内存结束)。但是,如果您看到不清楚的地方,请提出任何问题。
#include <iostream>
#include <string>
// Experiment with different types to see differences
// (and how data are truncated when sizeof number > sizeof networkdata)
//typedef unsigned int numberType_t;
typedef unsigned long numberType_t; // on my platform this is 8 bytes long
constexpr int networkBytesSize = 4; // number of chars to be sent trough network with (char *)
// define network data type:
// used "struct" to make sizeof(networkData_t) return actual number of bytes
typedef struct {
unsigned char d[networkBytesSize];
char *cptr() { return reinterpret_cast<char *>(d); }
} networkData_t;
// Writes number into network char* buffer nrAsByte, endianness agnostic
void number2char(numberType_t number, networkData_t & nrAsByte) {
for (size_t i = 0; i < sizeof(networkData_t); ++i) {
nrAsByte.d[i] = number & 0xFF;
number >>= 8;
}
}
// Read number back from network char* buffer
numberType_t char2number(const networkData_t & nrAsByte) {
numberType_t number = 0;
size_t i = sizeof(networkData_t);
while (i--) number = (number<<8) | nrAsByte.d[i];
return number;
}
int main()
{
printf("numberType_t size in bytes: %lu, networkData_t size in bytes: %lu\nAll following numbers are hex:\n",
sizeof(numberType_t), sizeof(networkData_t));
numberType_t number = numberType_t(0x9ABCDEF0123456FEul);
std::cout << "source number: " << std::hex << number << std::endl;
// Write number into char buffer
networkData_t networkData;
number2char(number, networkData);
std::cout << "network bytes:";
for (size_t i = 0; i < sizeof(networkData_t); ++i) std::cout << " [" << unsigned(networkData.d[i]) << "]";
std::cout << std::endl;
// Test usability of (char *) pointer access
const char * testCharPtrConversion = networkData.cptr();
printf("as char * (decimal signed): %d %d ...\n", testCharPtrConversion[0], testCharPtrConversion[1]);
// Read number from char buffer
number = char2number(networkData);
std::cout << "read number: 0x" << std::hex << number << std::endl;
}