alexandernst
alexandernst

Reputation: 15109

Comparing uint64_t with an unsigned char*

I have this POC

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

int main(void) {
    unsigned char *c = "This is ";
    uint64_t i;
    int j;
    i = c[7] | (c[6] << 8) | (c[5] << 16) | (c[4] << 24) | (c[3] << 32) | (c[2] << 40) | (c[1] << 48) | (c[0] << 56);
    printf("c value: '%s'\n", c);
    printf("Hex:");
    for (j = 0; j < 8; j++) {
        printf(" %2x", c[j]);
    }
    printf("\n");

    printf("Is i equal to c? %d\n", 
        memcmp((unsigned char *)&i, "\x54\x68\x69\x73\x20\x69\x73\x20", 8)
    );
    return 0;
}

I have an unsigned char * (please note the white space at the end!) and an uint64_t which I'm filling in with the data from the unsigned char *.

Then I memcmp both vars and I'd expect to get 0, but I get -1. Why is that?

I'm thinking it has something to do with how c is promoted in the bitwise operations, but I can't find exactly what is going wrong.

Upvotes: 0

Views: 857

Answers (1)

Giorgi Moniava
Giorgi Moniava

Reputation: 28654

If you take this code:

#include <stdio.h>
#include <stdint.h>
#include <string.h>
int main(void) {
    unsigned char *c = "This is ";
    uint64_t i;
    int j;
    i = (uint64_t ) c[7] | ((uint64_t )c[6] << 8) | ((uint64_t )c[5] << 16) | ((uint64_t )c[4] << 24) | ((uint64_t )c[3] << 32) | ((uint64_t )c[2] << 40) | ((uint64_t )c[1] << 48) | ((uint64_t )c[0] << 56);
    printf("c value: '%s'\n", c);
    printf("Hex:");
    for (j = 0; j < 8; j++) {
        printf(" %2x", c[j]);
    }
    printf("\n");

    printf("Printing i contents as they appear in memory \n");
    unsigned char *k=(unsigned char*)&i;
    for(int j = 0;j<8 ;j++)
        printf("%2x ",(unsigned) k[j]);
    printf("\n");

    printf("Is i is equal to c? %d\n",
           memcmp(&i, "\x54\x68\x69\x73\x20\x69\x73\x20", 8)
           );
    return 0;
}

The output on my machine which is little endian is:

    c value: 'This is '
    Hex: 54 68 69 73 20 69 73 20
    Printing i contents as they appear in memory 
    20 73 69 20 73 69 68 54 

You can see the bytes are reversed when stored in memory. This should give you clue that if your PC is little endian, i's least significant byte which is ' ' will be stored at the beginning in the memory address.

Upvotes: 3

Related Questions