Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Thứ tự Endian và file nhị phân trong C++

Trong quản lý file nhị phân và dữ liệu, Endianness (Thứ tự byte) là thứ tự sắp xếp các byte của một từ dữ liệu (word) trong bộ nhớ máy tính.

Hai loại Endian chính

  • Big-Endian (Đại đầu): Byte có trọng số lớn nhất (Most Significant Byte - MSB) được lưu ở địa chỉ bộ nhớ thấp nhất (địa chỉ bắt đầu). Đây là thứ tự tự nhiên con người đọc (ví dụ: số 0x12345678 lưu lần lượt 12 34 56 78). Thường dùng trong giao thức mạng (Network Byte Order).
  • Little-Endian (Tiểu đầu): Byte có trọng số nhỏ nhất (Least Significant Byte - LSB) được lưu ở địa chỉ bộ nhớ thấp nhất. Đây là kiến trúc phổ biến của các vi xử lý Intel x86, ARM (mặc định). Số 0x12345678 lưu: 78 56 34 12.

Tại sao quan trọng trong C++?

Khi ghi/đọc file nhị phân hoặc truyền dữ liệu qua mạng giữa các hệ thống khác nhau (Big vs Little Endian), dữ liệu sẽ bị hiểu sai nếu không chuyển đổi. Cần dùng các hàm chuyển đổi:

  • htonl(), htons() (Host to Network Long/Short) - Chuyển sang Big-Endian.
  • ntohl(), ntohs() (Network to Host Long/Short) - Chuyển từ Big-Endian về máy chủ.

Kiểm tra Endian của hệ thống tại runtime

#include <iostream>
using namespace std;

bool isLittleEndian() {
    uint32_t num = 0x01020304;
    // Ép con trỏ trỏ đến byte đầu tiên
    return *reinterpret_cast<uint8_t*>(&num) == 0x04;
}

int main() {
    if (isLittleEndian())
        cout << "He thong: Little-Endian";
    else
        cout << "He thong: Big-Endian";
    return 0;
}

Đầu ra (trên Intel/AMD)

He thong: Little-Endian

Ví dụ ghi/đọc file nhị phân an toàn Endian

#include <fstream>
#include <cstdint>
#include <arpa/inet.h> // htonl, ntohl (Linux/macOS). Windows: 

void writeInt32BE(ofstream& out, uint32_t val) {
    val = htonl(val); // Chuyển sang Network Order (Big-Endian)
    out.write(reinterpret_cast<char*>(&val), 4);
}

uint32_t readInt32BE(ifstream& in) {
    uint32_t val;
    in.read(reinterpret_cast<char*>(&val), 4);
    return ntohl(val); // Về Host Order
}