簡體   English   中英

在具有不同字節序的不同平台上使用 memcpy

[英]Using memcpy across different platforms which have different endianess

我正在編寫一個將數據從 uint32_t 復制到 std::vector 的函數。 該程序將在具有不同字節序的不同平台上使用(主要是 LE,但也有一些是 BE)

目前我正在使用這個:

std:vector<uint8_t> Decryption::GenerateIvForBlock(uint32_t blockNumber)
{
    std:vector<uint8_t> ivInput(AES128_KEY_BYTE_LENGTH, 0);

// Some code
if (///////)
{
    memcpy(&ivInput[0], &blockNumber, sizeof(blockNumber));
}
} 

目前,不同的字節序類型平台的行為是不同的,即使 blockNumber 在平台上是相同的。 不幸的是,我不能很容易地測試大端系統,所以我努力想出一個解決方案。

正如 πάντα ῥεῖ 建議的那樣, ntohx() / htonx()函數可以幫助您將 16 位和 32 位無符號積分從網絡字節順序轉換為主機字節順序並返回。

有一些草稿將ntoh()hton()模板包含在 C++ <net>標頭中,但是afaik,沒有成功。 您可能會在<Winsock2.h><arpa/inet.h>找到 C 函數,因此您可以自己創建模板。 例子:

#include <cstdint>
#ifdef _WIN32
 #include <Winsock2.h>
#else
 #include <arpa/inet.h>
#endif

template <class T>
T hton(T host) noexcept = delete;

template <>
uint8_t hton(uint8_t host) noexcept {
    return host;
}

template <>
uint16_t hton(uint16_t host) noexcept {
    return htons(host);
}

template <>
uint32_t hton(uint32_t host) noexcept {
    return htonl(host);
}

template <class T>
T ntoh(T network) noexcept = delete;

template <>
uint8_t ntoh(uint8_t network) noexcept {
    return network;
}

template <>
uint16_t ntoh(uint16_t network) noexcept {
    return ntohs(network);
}

template <>
uint32_t ntoh(uint32_t network) noexcept {
    return ntohl(network);
}

有了這些,您可以使用流運算符為您的向量創建一個包裝類模板來保存和恢復數據。 下面是一個非常基本的例子。 根據需要添加運算符等。

template <typename T>
class Data {
    std::vector<T> m_data;
public:
    Data() : m_data{} {}

    template< class... Args >
    auto emplace_back( Args&&... args ) {
        return m_data.emplace_back(std::forward<Args>(args)...);
    }
    void reserve(typename std::vector<T>::size_type size) {
        m_data.reserve(size);
    }
    bool operator==(const Data& o) {
        return m_data == o.m_data;
    }

    template <typename V>
    friend std::ostream& operator<<(std::ostream&, const Data<V>&);
    template <typename V>
    friend std::istream& operator>>(std::istream&, Data<V>&);
};

template <typename T>
std::ostream& operator<<(std::ostream& os, const Data<T>& d) {
    // write the number of entries first
    const uint32_t count = hton(static_cast<const uint32_t>(d.m_data.size()));
    os.write(reinterpret_cast<const char*>(&count), sizeof(count));
    // write all the entries, converted to network byte order
    for(auto v : d.m_data) {
        v = hton(v);
        os.write(reinterpret_cast<const char*>(&v), sizeof(v));
    }
    return os;
}

template <typename T>
std::istream& operator>>(std::istream& is, Data<T>& d) {
    // read the number of entries first
    uint32_t count;
    is.read(reinterpret_cast<char*>(&count), sizeof(count));
    d.m_data.resize(ntoh(count));
    // read all the entries and convert to host byte order
    for(auto& v : d.m_data) {
        is.read(reinterpret_cast<char*>(&v), sizeof(v));
        v = ntoh(v);
    }
    return is;
}

測試:

#include <iostream>
#include <vector>
#include <sstream>

int main() {
    Data<unsigned> orig;
    Data<unsigned> copy;
    std::stringstream ss;
    orig.reserve(1024*1024);
    for(unsigned i=0; i<1024*1024; ++i) orig.emplace_back(i);
    ss << orig; // save to stream
    // the data in 'ss' is now in network byte order
    ss >> copy; // restore from stream
    if(orig==copy) std::cout << "happy\n";
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM