一、对象地址与排列方式
我们首先需要明白,对于跨越多字节的程序对象,我们必须建立两个规则:
- 1)对象的地址是什么?在几乎所有的机器上,多字节对象都被存储为连续的字节序列,如
int
类型对象为四个字节序列,对象的地址为所使用的字节中的最小的地址。 - 2)如何排列这些字节?(大端法、小端法)
大端法:在内存中按照从最高有效字节到最低有效字节的顺序存储对象,最高有效字节在前面
小端法:在内存中按照从最低有效字节到最高有效字节的顺序存储对象,最低有效字节在前面
二、int、long、double类型与字节数组的转换
将int
类型的变量转成字节数组,下面这种转换用于在同一机器不同语言(Java与C++)之间交换数据时保持统一,所以不用考虑大小端,只需要将变量的最小地址和字节数组的首地址对应,依次将所有字节中的值放进去即可。同理long
和double
占用8个字节。
char* Int2Bytes(int32_t value) {
char *bytes = reinterpret_cast<char*>(malloc(4 * sizeof(char)));
char *minAdd = reinterpret_cast<char*>(&value);//取到最小地址
//变量value占用四个字节,所以只需要分别将四个字节依次放入字节数组即可
for (int i = 0; i < 4; i++) {
bytes[i] = *minAdd++;
}
return bytes;
}
int Bytes2Int(char *bytes) {
int value = *reinterpret_cast<int32_t*>(bytes);
return value;
}
char* Long2Bytes(int64_t value) {
char *bytes = reinterpret_cast<char*>(malloc(8 * sizeof(char)));
char *minAdd = reinterpret_cast<char*>(&value);
for (int i = 0; i < 8; i++) {
bytes[i] = minAdd[i];
}
return bytes;
}
long Bytes2Long(char *bytes) {
long value = *reinterpret_cast<int64_t*>(bytes);
return value;
}
char* Double2Bytes(double value) {
char *bytes = reinterpret_cast<char*>(malloc(8 * sizeof(char)));
char *minAdd = reinterpret_cast<char*>(&value);
for (int i = 0; i < 8; i++) {
bytes[i] = minAdd[i];
}
return bytes;
}
double Bytes2Dobule(char *bytes) {
double value = *(reinterpret_cast<double*>(bytes));
return value;
}
三、含有字符串的结构体与字节数组的转换
typedef struct {
int errCode;
char *errMassage;
char *errLocal;
} ExceptionVal;
char* ExceptionVal2Bytes(int code, const char *message, const char *local,
int &len) {
int index = 0;
int messageLen = 0;
int localLen = 0;
int bytesLen = 0;
while (message[messageLen] != '\0')
messageLen++;
while (local[localLen] != '\0')
localLen++;
len = bytesLen = 4 + 4 + 4 + messageLen + localLen;
char *bytes = reinterpret_cast<char*>(malloc(bytesLen * sizeof(char)));
char *messageLenBytes = Int2Bytes(messageLen);
char *localLenBytes = Int2Bytes(localLen);
char *codeBytes = Int2Bytes(code);
for (int i = 0; i < 4; i++)
bytes[index++] = messageLenBytes[i];
for (int i = 0; i < 4; i++)
bytes[index++] = localLenBytes[i];
for (int i = 0; i < 4; i++)
bytes[index++] = codeBytes[i];
for (int i = 0; i < messageLen; i++)
bytes[index++] = message[i];
for (int i = 0; i < localLen; i++)
bytes[index++] = local[i];
return bytes;
}
ExceptionVal* Bytes2ExceptionVal(char *bytes) {
ExceptionVal *excepVal = reinterpret_cast<ExceptionVal*>(malloc(
sizeof(ExceptionVal)));
int index = 0;
char *messageLenBytes = reinterpret_cast<char*>(malloc(4 * sizeof(char)));
char *localLenBytes = reinterpret_cast<char*>(malloc(4 * sizeof(char)));
char *codeBytes = reinterpret_cast<char*>(malloc(4 * sizeof(char)));
for (int i = 0; i < 4; i++)
messageLenBytes[i] = bytes[index++];
for (int i = 0; i < 4; i++)
localLenBytes[i] = bytes[index++];
for (int i = 0; i < 4; i++)
codeBytes[i] = bytes[index++];
int messageLen = Bytes2Int(messageLenBytes);
int localLen = Bytes2Int(localLenBytes);
char *errMessage = reinterpret_cast<char*>(malloc(
(messageLen + 1) * sizeof(char)));
char *errLocal = reinterpret_cast<char*>(malloc(
(localLen + 1) * sizeof(char)));
excepVal->errCode = Bytes2Int(codeBytes);
for (int i = 0; i < messageLen; i++)
errMessage[i] = bytes[index++];
errMessage[messageLen] = '\0';
excepVal->errMassage = errMessage;
for (int i = 0; i < localLen; i++)
errLocal[i] = bytes[index++];
errLocal[localLen] = '\0';
excepVal->errLocal = errLocal;
return excepVal;
}
四、测试及其结果
#include <iostream>
/**
* 假装这里有前面出现的所有方法
*/
void printBytes(char *bytes, int size) {
printf("\nbyteArry:");
for (int i = 0; i < size; i++) {
printf("%d", bytes[i]);
if (i < size - 1)
printf(",");
else
printf("\n");
}
}
int main() {
// int 类型互转
int32_t intVal = 154654600;
char *bytes1 = Int2Bytes(intVal);
printBytes(bytes1, 4);
std::cout << Bytes2Int(bytes1) << std::endl;
// long 类型互转
int64_t longVal = 1254546132;
char *bytes2 = Long2Bytes(longVal);
printBytes(bytes2, 8);
std::cout << Bytes2Long(bytes2) << std::endl;
// double 类型互转
double doubleVal = 3.1415;
char *bytes3 = Double2Bytes(doubleVal);
printBytes(bytes3, 8);
std::cout << Bytes2Dobule(bytes3) << std::endl;
// 带有字符串的struct 类型转换
int errCode = 1245216;
const char *errMessage = "too many local cursor";
const char *errLocal = "At FUN2_I_DATE_S_1 Line 10, Column 0";
int len = 0;
char *bytes4 = ExceptionVal2Bytes(errCode, errMessage, errLocal, len);
printBytes(bytes4, len);
ExceptionVal *excepVal = Bytes2ExceptionVal(bytes4);
std::cout << excepVal->errCode << std::endl;
std::cout << excepVal->errMassage << std::endl;
std::cout << excepVal->errLocal << std::endl;
return 0;
}