Hm, I've been toying around with Antonio's answer, as it didn't feel complete and correct, and in the end I ended with something more complex than I expected, but complexity has it's purpose sometimes.
Following code is doing among other things also htonl/ntohl-like conversion manually (maybe in opposite endianness, so it's not desirable to mix this with htonl, use either this, or rewrite it with htonl).
Unlike Antonio's source, it will not overwrite memory when input number type is 8 bytes long (unsigned long is 8 bytes on my test platform - BTW, try it?!), it will instead truncate the value to fit into the desired network char* buffer.
I tried to comment it extensively to give you idea behind each decision to add further complexity (to what is basically using unsigned int number used as (char *)(&number), which delivers too, but doesn't guard endianness, and may end in overwriting memory if you mix up different length types). But ask anything if you see something unclear.
#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;
}