Ye Wang
Ye Wang

Reputation: 43

C++: Convert unsigned long int into vector<uint8_t> raw data

I need to convert a long int x = 0x9c758d0f into a vector<uint8_t> y = 9c 75 8d 0f.

I was using:

std::stringsteam ss;
ss << std::hex << x;

std::string s = ss.str();

std::vector<uint8_t> y;
String2Vector(s,y);

    void String2Vector(std::string& in, std::vector<uint8_t>& output) 
    {
        std::vector<uint8_t> out;
        size_t len = in.length();

        for(size_t i = 0; i < len; i += 1) 
        {
            std::stringstream strm(in.substr(i, 1));
            uint8_t x;
            strm  >>std::hex>> x;
            out.push_back(x);
        }
        output = out;
    }

However, the vector<uint8_t> stored ASCII number instead of hex value.

What should I do in order to convert a long int into a raw data vector? It's a multi-platform project so I don't wanna touch memcpy() etc.


Update: Pretty sure something went wrong:

long int x = 0x9c758d0f;
std::vector<uint8_t> v;
v.reserve(sizeof(x));
for (size_t i = 0; i < sizeof(x); ++i) {
    v.push_back(x & 0xFF);
    x = (x>>8);
}
PrintOutVector(v);

void PrintOutVector(std::vector<uint8_t>& in)
    {
        std::cout << "Vector Contains: ";
        for(std::vector<uint8_t>::iterator i=in.begin(); i != in.end(); ++i)
            std::cout << std::hex <<  *i ;
        std::cout << "\n";
    }

the output is ▒C▒▒h4


Solution: Much thanx to @WhozCraig @Anton Savin

long int x = 0x9c758d0f;
std::vector<uint8_t> v;
v.reserve(sizeof(x));
for (size_t i = 0; i < sizeof(x); ++i) {
    v.push_back(x & 0xFF);
    x = (x>>8);
}
PrintOutVector(v);

void PrintOutVector(std::vector<uint8_t>& in)
    {
        std::cout << "Vector Contains: ";
        for(std::vector<uint8_t>::iterator i=in.begin(); i != in.end(); ++i)
            std::cout << std::hex <<  static_cast<unsigned int>(*i)
        std::cout << "\n";
    }

Upvotes: 2

Views: 4221

Answers (3)

Anton Savin
Anton Savin

Reputation: 41301

Here is a solution which provides same results regardless of byte ordering:

long int x = 0x9c758d0f;
std::vector<uint8_t> v;
v.reserve(sizeof(x));
for (size_t i = 0; i < sizeof(x); ++i) {
    v.push_back(x & 0xFF);
    x >>= 8;
}

Upvotes: 2

Arun R
Arun R

Reputation: 891

Unions come in handy for this sort of stuff. Only issue is the byte ordering might vary based on endianness, which you have to account for.

union U{
    long int i;
    uint8_t uc[4];
};
U u = {0x9c758d0f};
std::vector<uint8_t> ucvec(u.uc, u.uc+4);
printf ("%x:%x:%x:%x\n", ucvec[3], ucvec[2], ucvec[1], ucvec[0]);

Upvotes: 0

John Zwinck
John Zwinck

Reputation: 249093

long int x = 0x9c758d0f;
const uint8_t* begin = reinterpret_cast<const uint8_t*>(&x);
const uint8_t* end = begin + sizeof(x);
std::vector<uint8_t> v(begin, end);

Note that the ordering depends on how your system arranges the bytes (big endian or little endian) in the long. You can deal with this by first reordering the bytes to big-endian with a function like htonl(), except that is for int and there is no cross-platform one for long so you'll have to think about what to do there if you care about the byte ordering.

Upvotes: 2

Related Questions