簡介: CSDN博客專家,專注Android/Linux系統,分享多mic語音方案、音視頻、編解碼等技術,與大家一起成長!
優質專欄:Audio工程師進階系列【原創干貨持續更新中……】🚀
優質專欄:多媒體系統工程師系列【原創干貨持續更新中……】🚀
優質視頻課程:AAOS車載系統+AOSP14系統攻城獅入門實戰課【原創干貨持續更新中……】🚀
人生格言: 人生從來沒有捷徑,只有行動才是治療恐懼和懶惰的唯一良藥.
🍉🍉🍉文章目錄🍉🍉🍉
- 🌻1.前言
- 🌻2.大小端介紹
- 🐓2.1 大端模式
- 🐓2.2 小端模式
- 🐓2.3 作用及應用
- 🐓2.4結論
- 🌻3.代碼實例
- 🐓3.1 C++處理大端、小端數據
- 🐓3.2 Android處理大端、小端數據
- 🐓3.3 C語言處理大端、小端數據
🌻1.前言
本篇目的:C++與Android處理16進制大端/小端數據實例
🌻2.大小端介紹
- 大小端模式是指計算機系統中多字節數據的存儲方式和傳輸方式,它主要分為大端模式(Big-Endian)和小端模式(Little-Endian)。
🐓2.1 大端模式
- 在大端模式中,高字節存儲在低地址位置,而低字節存儲在高地址位置。換句話說,一個數的最高有效字節(Most Significant Byte, MSB)存放在內存的起始位置。大端模式的特點是數據的書寫順序與其在內存中的存儲順序一致,這樣在查看內存時,數據看起來更直觀。例如,對于一個32位整數0x12345678,在大端模式下的存儲順序如下:
地址 值
0x00 12
0x01 34
0x02 56
0x03 78
🐓2.2 小端模式
小端模式則是將低字節存儲在低地址位置,高字節存儲在高地址位置。即最低有效字節(Least Significant Byte, LSB)放在內存的起始位置。與大端模式相反,小端模式的數據存儲順序和書寫順序相反。例如,對于同樣的32位整數0x12345678,在小端模式下的存儲順序如下:
地址 值
0x00 78
0x01 56
0x02 34
0x03 12
🐓2.3 作用及應用
- 大小端模式的選擇與計算機的體系結構和應用需求有關。不同的處理器體系結構可能會采用不同的字節存儲方式。
-
網絡通信:在網絡通信中,大端模式(也稱為網絡字節序)被廣泛采用。這是因為大端模式在數據傳輸時,最高有效字節先傳輸,便于數據在不同系統之間進行一致的傳遞和解釋。互聯網協議(如TCP/IP)就使用大端模式,這使得不同設備之間的數據交換更為統一和標準化。
-
跨平臺數據處理:當程序需要在不同平臺上運行時(例如在不同的處理器架構之間傳遞數據),了解并處理大小端模式是必要的。某些處理器(如x86架構)采用小端模式,而其他處理器(如某些RISC架構)可能采用大端模式。在這種情況下,程序需要正確地轉換數據的字節順序,以確保數據的一致性和正確性。
-
文件格式和數據存儲:某些文件格式或數據存儲協議可能規定了特定的字節序。例如,WAV音頻文件和許多圖像文件格式規定了使用小端模式存儲數據。這種規定確保了文件在不同系統上讀取時的一致性。
🐓2.4結論
- 大小端模式是計算機系統中處理多字節數據的重要概念,理解和正確應用這些模式對于開發跨平臺軟件、網絡協議和處理特定文件格式至關重要。
- 大端模式以其直觀的內存布局適用于網絡通信和標準化的數據傳輸,而小端模式由于其在某些處理器上的效率優勢,被廣泛應用于多種處理器架構中。在實際應用中,根據具體需求選擇合適的字節序模式是確保數據正確處理的關鍵。
🌻3.代碼實例
🐓3.1 C++處理大端、小端數據
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdint>// 判斷系統是否為小端
bool isLittleEndian() {uint16_t number = 0x1;return (*(char *)&number == 0x1);
}// 進行字節序轉換(32位)
uint32_t swapEndian32(uint32_t val) {return ((val >> 24) & 0x000000FF) |((val >> 8) & 0x0000FF00) |((val << 8) & 0x00FF0000) |((val << 24) & 0xFF000000);
}// 打印緩沖區內容(小端字節序)
void printBufferLittleEndian(const std::vector<uint8_t>& buffer, const std::string& bufferName) {std::string bufferHex;for (size_t i = 0; i < buffer.size(); i += 4) {uint32_t val = 0;// 讀取4個字節for (size_t j = 0; j < 4 && (i + j) < buffer.size(); ++j) {val |= (static_cast<uint32_t>(buffer[i + j]) << (j * 8));}// 如果系統不是小端字節序,則需要轉換字節序if (!isLittleEndian()) {val = swapEndian32(val);}// 將4字節的值轉換為十六進制字符串std::ostringstream hexStream;hexStream << std::setfill('0') << std::setw(8) << std::hex << val;bufferHex += hexStream.str() + " ";}std::cout << bufferName << ": " << bufferHex << std::endl;
}// 打印write_buffer的內容
void printWriteBuffer(const std::vector<uint8_t>& writeBuffer) {printBufferLittleEndian(writeBuffer, "Write Buffer");
}// 打印read_buffer的內容
void printReadBuffer(const std::vector<uint8_t>& readBuffer) {printBufferLittleEndian(readBuffer, "Read Buffer");
}int main() {// 初始化示例數據std::vector<uint8_t> writeBuffer(256);for (int i = 0; i < 256; ++i) {writeBuffer[i] = static_cast<uint8_t>(i);}std::vector<uint8_t> readBuffer(256);for (int i = 0; i < 256; ++i) {readBuffer[i] = static_cast<uint8_t>(255 - i);}// 打印緩沖區內容printWriteBuffer(writeBuffer);printf("\n");printReadBuffer(readBuffer);return 0;
}
🐓3.2 Android處理大端、小端數據
#include <cutils/log.h>
#include <iomanip>
#include <stdint.h>// 判斷系統是否為小端
bool isLittleEndian() {uint16_t number = 0x1;return (*(char *)&number == 0x1);
}// 進行字節序轉換(32位)
uint32_t swapEndian32(uint32_t val) {return ((val >> 24) & 0x000000FF) |((val >> 8) & 0x0000FF00) |((val << 8) & 0x00FF0000) |((val << 24) & 0xFF000000);
}// 打印緩沖區內容(小端字節序)
void printBufferLittleEndian(const char* buffer, size_t size, const char* bufferName) {std::string bufferHex;for (size_t i = 0; i < size; i += 4) {uint32_t val = 0;// 讀取4個字節for (size_t j = 0; j < 4 && (i + j) < size; ++j) {val |= (static_cast<uint32_t>(static_cast<uint8_t>(buffer[i + j])) << (j * 8));}// 如果系統不是小端字節序,則需要轉換字節序if (!isLittleEndian()) {val = swapEndian32(val);}// 將4字節的值轉換為十六進制字符串char hex[9];snprintf(hex, sizeof(hex), "%08x", val);bufferHex += hex;bufferHex += " ";}ALOGE("%s: %s", bufferName, bufferHex.c_str());
}// 打印write_buffer的內容
void printWriteBuffer(const binder_write_read& bwr) {const char* writeBuffer = reinterpret_cast<const char*>(bwr.write_buffer);printBufferLittleEndian(writeBuffer, bwr.write_size, "Write Buffer");
}// 打印read_buffer的內容
void printReadBuffer(const binder_write_read& bwr) {const char* readBuffer = reinterpret_cast<const char*>(bwr.read_buffer);printBufferLittleEndian(readBuffer, bwr.read_size, "Read Buffer");
}int main() {binder_write_read bwr;// 初始化示例數據bwr.write_size = 256;char writeData[256];for (int i = 0; i < 256; ++i) {writeData[i] = i;}bwr.write_buffer = reinterpret_cast<binder_uintptr_t>(writeData);bwr.read_size = 256;char readData[256];for (int i = 0; i < 256; ++i) {readData[i] = 255 - i;}bwr.read_buffer = reinterpret_cast<binder_uintptr_t>(readData);// 打印緩沖區內容printWriteBuffer(bwr);printReadBuffer(bwr);return 0;
}
🐓3.3 C語言處理大端、小端數據
/***********************************************************
* Author : 公眾號: Android系統攻城獅
* Create time : 2024-05-21 10:07:14 星期二
* Filename : little_big_duan_for_C.cpp
* Description :
************************************************************/#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>// 判斷系統是否為小端
bool isLittleEndian() {uint16_t number = 0x1;return (*(char *)&number == 0x1);
}// 進行字節序轉換(32位)
uint32_t swapEndian32(uint32_t val) {return ((val >> 24) & 0x000000FF) |((val >> 8) & 0x0000FF00) |((val << 8) & 0x00FF0000) |((val << 24) & 0xFF000000);
}// 打印緩沖區內容(小端字節序)
void printBufferLittleEndian(const char* buffer, size_t size, const char* bufferName) {char bufferHex[1024] = {0}; // 假設緩沖區最大為1024字節char hex[9];for (size_t i = 0; i < size; i += 4) {uint32_t val = 0;// 讀取4個字節for (size_t j = 0; j < 4 && (i + j) < size; ++j) {val |= (uint32_t)((uint8_t)buffer[i + j]) << (j * 8);}// 如果系統不是小端字節序,則需要轉換字節序if (!isLittleEndian()) {val = swapEndian32(val);}// 將4字節的值轉換為十六進制字符串snprintf(hex, sizeof(hex), "%08x", val);strncat(bufferHex, hex, sizeof(bufferHex) - strlen(bufferHex) - 1);strncat(bufferHex, " ", sizeof(bufferHex) - strlen(bufferHex) - 1);}printf("%s: %s\n", bufferName, bufferHex);
}// 假設binder_write_read_01結構如下
typedef struct {void* write_buffer;size_t write_size;void* read_buffer;size_t read_size;
} binder_write_read_01;// 打印write_buffer的內容
void printWriteBuffer(const binder_write_read_01* bwr) {const char* writeBuffer = (const char*)(bwr->write_buffer);printBufferLittleEndian(writeBuffer, bwr->write_size, "Write Buffer");
}// 打印read_buffer的內容
void printReadBuffer(const binder_write_read_01* bwr) {const char* readBuffer = (const char*)(bwr->read_buffer);printBufferLittleEndian(readBuffer, bwr->read_size, "Read Buffer");
}int main() {// 示例使用uint8_t write_data[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};uint8_t read_data[] = {0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10};binder_write_read_01 bwr = {write_data, sizeof(write_data), read_data, sizeof(read_data)};printWriteBuffer(&bwr);//printReadBuffer(&bwr);return 0;
}