Anne
Anne

Reputation: 123

Concatenate two 64bit integer and store it into a uint8_t array of [16]

I want to concatenate a 64bit integer len_A with a 64bit integer len_C and store it into a uint8_t buffer[16]. But I couldnt do it even it I have assign len_A as (uint8_t *) len_A and len_C (uint8_t *) len_C.

The warning message was: cast to pointer from integer of different size

uint64_t len_A
uint64_t len_C
uint8_t buffer[16] = { 0 };

for (k = 7, l = 0; k >= 0 && l <= 7; k--, l++) {
    buffer[k] = buffer[k] ^ ((uint8_t *) len_A)[l];
}
for (k = 15, l = 0; k >= 8 && l <= 7; k--, l++) {
    buffer[k] = buffer[k] ^ ((uint8_t *) len_C)[l];
}

I've also done it in another way:

for (k = 15; k >= 0; k--) {
    if(k==0){
        buffer[k] = buffer[k] ^ (len_A && 0xff); // lowest byte 0 len_A
    }
    if(k!=0){
        buffer[k] = buffer[k] ^ ((len_A >> 8*k) & 0xff); // byte no 2 of len_A
    }
}
k=15;
for (k = 15; k>=7; k--) {
    if(k==0){
        buffer[k] = buffer[k] ^ (len_C && 0xff); // lowest byte 0 len_A
        }
    if(k!=0){
        buffer[k] = buffer[k] ^ ((len_C >> 8*k) & 0xff); // byte no 2 of len_A
    }
}

But still the compiler seems to point to an unknown address and giving the wrong results.

Are there any other options?

Upvotes: 0

Views: 1004

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 753695

It is curious that you use the xor operator. It will work OK if (because) the target area is already zero, but it seems a little circuitous; you should be using plain assignment. Notationally, there is also a ^= operator that could be used to simplify the last proposed assignment to:

buffer[k] ^= ((len_C >> 8*k) & 0xFF);

(though the ^ should be omitted in this context).

Your problem in the first example is that you needed ((uint8_t *) &len_A)[l] (and no xor).

uint64_t len_A;
uint64_t len_C;
uint8_t buffer[16] = { 0 };

for (k = 7, l = 0; k >= 0 && l <= 7; k--, l++)
    buffer[k] = ((uint8_t *)&len_A)[l];
for (k = 15, l = 0; k >= 8 && l <= 7; k--, l++)
    buffer[k] = ((uint8_t *)&len_C)[l];

This copies the data bytes into the buffer in the reverse order that they're found in memory. Solutions using memcpy() won't do that reversal.

The loop controls are still more complex than necessary. You could simplify the code to:

for (k = 7; k >= 0; k--)
    buffer[k] = ((uint8_t *)&len_A)[7-k];
for (k = 15; k >= 8; k--)
    buffer[k] = ((uint8_t *)&len_C)[15-k];

In the second example, you'll be shifting by more bits than there are in the len_A which will lead to trouble; you need to shift by ((k - 8) * 8). It is legal to shift by zero, so you don't need to special case that. I've adjusted the bounds on both loops.

for (k = 7; k >= 0; k--)
     buffer[k] = (len_A >> (8*k)) & 0xFF;
for (k = 15; k>= 8; k--)
     buffer[k] = (len_C >> (8*(k-8))) & 0xFF;

I note that this third pair of loops do not do the byte-order reversal, though that's easily fixed:

for (k = 7; k >= 0; k--)
     buffer[k] = (len_A >> (8*(8-k))) & 0xFF;
for (k = 15; k>= 8; k--)
     buffer[k] = (len_C >> (8*(15-k))) & 0xFF;

Here's some demonstration output and code.

A = 0x0123456789ABCDEF
C = 0x0F1E2D3C4B5A6978
Loops 1:  01 23 45 67 89 AB CD EF : 0F 1E 2D 3C 4B 5A 69 78 :
Loops 2:  01 23 45 67 89 AB CD EF : 0F 1E 2D 3C 4B 5A 69 78 :
Loops 3:  EF CD AB 89 67 45 23 01 : 78 69 5A 4B 3C 2D 1E 0F :
Loops 4:  00 01 23 45 67 89 AB CD : 0F 1E 2D 3C 4B 5A 69 78 :

Code:

#include <stdint.h>
#include <stdio.h>

static void dump_buffer(size_t n, uint8_t const *data)
{
    for (size_t i = 0; i < n; i++)
    {
        printf(" %.2X", data[i]);
        if (i % 8 == 7)
            printf(" :");
    }
    putchar('\n');
}

int main(void)
{
    uint64_t len_A = 0x0123456789ABCDEF;
    uint64_t len_C = 0x0F1E2D3C4B5A6978;
    uint8_t  buffer[16] = { 0 };

    printf("A = 0x%.16llX\nC = 0x%.16llX\n", len_A, len_C);

    for (int k = 7, l = 0; k >= 0 && l <= 7; k--, l++)
        buffer[k] = ((uint8_t *)&len_A)[l];
    for (int k = 15, l = 0; k >= 8 && l <= 7; k--, l++)
        buffer[k] = ((uint8_t *)&len_C)[l];

    printf("Loops 1: ");
    dump_buffer(sizeof(buffer), buffer);

    for (int k = 7; k >= 0; k--)
        buffer[k] = ((uint8_t *)&len_A)[7-k];
    for (int k = 15; k >= 8; k--)
        buffer[k] = ((uint8_t *)&len_C)[15-k];

    printf("Loops 2: ");
    dump_buffer(sizeof(buffer), buffer);

    for (int k = 7; k >= 0; k--)
        buffer[k] = (len_A >> (8*k)) & 0xFF;
    for (int k = 15; k>= 8; k--)
        buffer[k] = (len_C >> (8*(k-8))) & 0xFF;

    printf("Loops 3: ");
    dump_buffer(sizeof(buffer), buffer);

    for (int k = 7; k >= 0; k--)
        buffer[k] = (len_A >> (8*(8-k))) & 0xFF;
    for (int k = 15; k>= 8; k--)
        buffer[k] = (len_C >> (8*(15-k))) & 0xFF;

    printf("Loops 4: ");
    dump_buffer(sizeof(buffer), buffer);

    return 0;
}

Upvotes: 2

Charlie Burns
Charlie Burns

Reputation: 7044

Try this:

memcpy(buffer, &len_A, sizeof(len_A));
memcpy(buffer + sizeof(len_A), &len_C, sizeof(len_C));

The first line copies sizeof(len_A) ( 8 ) bytes to &buffer[0].

The second line copies sizeof(len_C) ( 8 ) bytes to &buffer[sizeof(len_A)] ( 8 )


Note that this does not copy the bytes in the same order as the OP's algorithm. It was not clear to me if that was required. See comments below.

Upvotes: 3

creichen
creichen

Reputation: 1768

Your code seems very complex. Why not try to copy the memory directly (assuming that your data is aligned appropriately, which you can ensure e.g. via aligned_alloc()):

((uint64_t *)buffer)[0] = len_A
((uint64_t *)buffer)[1] = len_C

Which one is len_C and which one is len_C depends on the machine's endianness (if len_A is the more significant value, you want the above solution iff you are big-endian. If len_C is the more significant value, you want the above solution iff you are little-endian.) Otherwise, swap len_A and len_C in the above.

Upvotes: 0

Related Questions