Search code examples
cpointerspointer-arithmeticstrict-aliasing

Accessing bytes in a long long variable with pointers


I'm supposed to create a variable

long long hex = 0x1a1b2a2b3a3b4a4bULL;

and then define 4 pointers that point to 1a1b, 2a2b, 3a3b and 4a4b. I'm then printing the addresses and values of those double bytes.

My approach was to create a pointer

long long *ptr1 = &hex;

and then use pointer arithmetic to get to the next value. What I realized was that incrementing this pointer would increment it by long long bytes and not by 2 bytes like I need it to. Creating a short pointer

short *ptr1 = &hex;

Is what I would need but my compiler won't let me since the data types are incompatible. How do I get around that? Is there a way to create a pointer that increments by 2 bytes and assign that to a variable of a larger data type?


Solution

  • You can access any variable only through compatible types.

    However, a char pointer can be used to access any type of variable.

    Please do not cast it to a short* Please see NOTE below , they are not compatible types. You can only use a char* for conforming code.

    Quoting C11, chapter §6.3.2.3

    [...] When a pointer to an object is converted to a pointer to a character type, the result points to the lowest addressed byte of the object. Successive increments of the result, up to the size of the object, yield pointers to the remaining bytes of the object.

    So, the way out is, use a char * and use pointer arithmetic to get to the required address.


    NOTE: Since all other answers suggest a blatantly wrong method (casting the pointer to short *, which explicitly violates strict aliasing), let me expand a bit on my answer and supporting quotes.

    Quoting C11, chapter §6.5/P7

    An object shall have its stored value accessed only by an lvalue expression that has one of the following types: 88)

    — a type compatible with the effective type of the object,

    — a qualified version of a type compatible with the effective type of the object,

    — a type that is the signed or unsigned type corresponding to the effective type of the object,

    — a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,

    — an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union), or

    — a character type.

    In this case, a short and a long long are not compatiable types. so the only way out is to use pointer tochar` type.


    Cut-'n-Paste from Question body

    This was added as update by OP

    Edit: Here's the correct solution that doesn't cause undefined behavior. Edit 2: Added the memory address.

    #include <stdio.h>
    int main() {
        long long hex = 0x1a1b2a2b3a3b4a4bULL;
        char *ptr = (char*)&hex;
        int i; int j;
        for (i = 1, j = 0; i < 8, j < 7; i += 2, j += 2) {
            printf("0x%hx%hx at address %p \n", ptr[i], ptr[j], (void *) ptr+i);
        }
        return 0;
    }