Maciej Wojcik
Maciej Wojcik

Reputation: 2171

Divide char* into few variables

I have some char array: char char[8] which containing for example two ints, on first 4 indexes is first int, and on next 4 indexes there is second int.

char array[8] = {0,0,0,1,0,0,0,1};
int a = array[0-3]; // =1;  
int b = array[4-8]; // =1;

How to cast this array to two int's?

There can be any other type, not necessarily int, but this is only some example:

I know i can copy this array to two char arrays which size will be 4 and then cast each of array to int. But i think this isn't nice, and breaks the principle of clean code.

Upvotes: 3

Views: 103

Answers (3)

PaulMcKenzie
PaulMcKenzie

Reputation: 35440

Let's use a little bit of the C++ algorithms, such as std::accumulate:

#include <numeric>
#include <iostream>

int getTotal(const char* value, int start, int end)     
{
    return std::accumulate(value + start, value + end, 0, 
                           [](int n, char ch){ return n * 10 + (ch-'0');});
}

int main()
{
    char value[8] = {'1','2','3','4','0','0','1','4'};
    int total1 = getTotal(value, 0, 4);
    int total2 = getTotal(value, 4, 8);
    std::cout << total1 << " " << total2;
}

Note the usage of std::accumulate and the lambda function. All we did was have a running total, multiplying each subtotal by 10. The character is translated to a number by simply subtracting '0'.

Live Example

Upvotes: 1

Vivek
Vivek

Reputation: 330

You can type cast the bytes from the array to an int *. Then dereferencing will cause 4 bytes to be read as an int. Then doing an ntohl, will ensure that the bytes in the int are arranged as per the host order.

char array[8] = {0,0,0,1,0,0,0,1};

int a = *((int *)array);  
int b = *((int *)&array[4]);

a = ntohl(a);  
b = ntohl(b);

This will set a and b to 1 on both little and big endian systems.

If the compiler is set for strict aliasing, memcpy could be used to achieve the same, as follows:

char array[8] = {0,0,0,1,0,0,0,1};
int a, b;

memcpy(&a, array, sizeof(int));
memcpy(&b, array+4, sizeof(int));

a = ntohl(a);  
b = ntohl(b);  

Upvotes: -1

Ben Voigt
Ben Voigt

Reputation: 283634

If your data has the correct endianness, you can extract blitable types from a byte buffer with memcpy:

int8_t array[8] = {0,0,0,1,0,0,0,1};
int32_t a, b;
memcpy(&a, array + 0, sizeof a);
memcpy(&b, array + 4, sizeof b);

While @Vivek is correct that ntohl can be used to normalize endianness, you have to do that as a second step. Do not play games with pointers as that violates strict aliasing and leads to undefined behavior (in practice, either alignment exceptions or the optimizer discarding large portions of your code as unreachable).

int8_t array[8] = {0,0,0,1,0,0,0,1};
int32_t tmp;
memcpy(&tmp, array + 0, sizeof tmp);
int a = ntohl(tmp);
memcpy(&tmp, array + 4, sizeof tmp);
int b = ntohl(tmp);

Please note that almost all optimizing compilers are smart enough to not call a function when they see memcpy with a small constant count argument.

Upvotes: 6

Related Questions