うーん、私はアントニオの答えをいじっていました。完全で正しいとは感じなかったので、最終的には予想よりも複雑なもので終わりましたが、複雑さには目的がある場合があります。
次のコードは、とりわけ手動でhtonl
/のntohl
ような変換を行っています (おそらく反対のエンディアンであるため、これを と混ぜhtonl
たり、どちらかを使用したり、 で書き直したりすることは望ましくありません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;
}