简体   繁体   中英

Access elements of an unsigned char array as integers

I have to use a reading function that only accepts *unsigned char as input,

typedef unsigned char byte;
byte * rx_data;
rx_data = new byte [RX_PACKET_LEN*packets];

How can I read rx_data as an array of integers (4bytes) in a easy way?

You can cast it:

int* pInt = reinterpret_cast<int*>( rx_data);

or

int* pInt = (int*) rx_data;

or if you want to keep the name, cast it when you need to read from it:

((int*)rx_data)[0];

Note that you should only do this if you're absolutely sure what you're doing, otherwise it's not safe. (well, this ca apply anywhere, I know, but this demands special attention). Something that comes to mind - RX_PACKET_LEN*packets should be a multiple of sizeof(int) .

Since this is C++, you should use reinterpret_cast to cast the unsigned char pointer to an int pointer:

int * data = reinterpret_cast<int*>(rx_data);

However, this assumes that the data is stored in a particular endian format so if the array of chars is coming from a different platform with different endianness, this code would not work. If you assume the same platform, then you'll probably be okay.

The only safe way in a general setting is to make a copy:

std::vector<int32_t> target(RX_PACKET_LET * packets / sizeof(int32_t));

std::copy(rx_data, rx_data + RX_PACKET_LET * packets,
          reinterpret_cast<unsigned char *>(target.data()));

Now you can read target[0] , target[1] , ... as integers.

You can use memcpy for this.

byte *rx_data = ...
size_t rx_data_size = ...

std::array<int, rx_data_size/sizeof(int)> data;

std::memcpy(data.get(), rx_data, data.size() * sizeof(int));

// read and modify data

// if you need to write it back out to rx_data then copy data back when you're done

std::memcpy(rx_data, data.get(), data.size() * sizeof(int));

This has an advantage in that it involves no casting, handles unaligned memory, and does not rely on arcane aliasing rules.

One disadvantage may be that copying the data could result in lower performance. However this isn't guaranteed. Modern compilers usually implement memcpy as a compiler intrinsic and optimizers can reason about its behavior.

I just tried out LLVM and found that these:

void increment(char *buf) {
    int i;
    memcpy(&i,buf,sizeof(int));
    ++i;
    memcpy(buf,&i,sizeof(int));
}

void increment(int &i) {
    ++i;
}

produce almost identical IR representations (clang tmp.cpp -emit-llvm -o - | opt -S -O2) and exactly identical x86_64 assembly.

When you are changing the pointer type from byte* to int*, you will automatically read 4 bytes or jump 4 bytes when you will increment the pointer (p++). Just be sure that the byte array size is module 4 so you won't have segmentation fault.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM