0

I've got moderately stuck, googling the right words can't got me to the right answer. Even worse, I've already done that but my own code example lost somewhere in the source code.

#include <stdio.h>

int main()
{
    short x = 0xABCD;
    char y[2] = { 0xAB, 0xCD };
    printf("%x %x\n", y[0], y[1]);
    printf("%x %x\n", (char *)&x[0], (char *)&x[1]);
}

Basically I need to access individual variable bytes via array by pointer arithmetic, without any calculations, just by type casting.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
Art Navsegda
  • 25
  • 1
  • 1
  • 6

3 Answers3

3

Put parentheses around your cast:

printf("%x %x\n", ((char *)&x)[0], ((char *)&x)[1]);

Note that endian-ness may change your expected result.

In the future, compile with -Wall to see what the warnings or errors are.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
1

It's somewhat supported in C99. By a process known as type punning via union.

union {
  short s;
  char c[2];
} pun;

pun.s = 0xABCD;
pun.c[0] // reinterprets the representation of pun.s as char[2].
         // And accesses the first byte.

Pointer casting (as long as it's to char*, to avoid strict aliasing violations) is also ok.

short x = 0xABCD;
char *c = (char*)&x;
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • 1
    Of course, casting a pointer to `(void *)` is also fine (and necessary if you want to print the value held by a pointer using `%p`). – ad absurdum Jan 01 '17 at 07:41
  • Sorry to bother, but isn't it like reading a value of a member other that which was written last in an union, invokes UB? – Sourav Ghosh Jan 01 '17 at 07:43
  • 1
    @SouravGhosh - [The restriction was removed in C99 and onward](http://stackoverflow.com/a/11640603/817643). Only a warning for a possible trap is included, as well as a note that the result depends on the representation of the values. – StoryTeller - Unslander Monica Jan 01 '17 at 07:45
1

If you're only bothered about getting the values, you can store the address of the source variable in a char * and increment and dereference the char pointer to print the values of each byte.

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.

Something like (consider pseudo-code, not tested)

#include  <stdio.h>

int main(void)
{
    int src = 0x12345678;
    char * t = &src;

    for (int i = 0; i < sizeof(src); i++)
        printf("%x\t", t[i]);

    return 0;
}

should do it.


That said, to elaborate on the accepted answer, the why part:

As per the operator precedence table, array indexing operator has higher precedence over the type-casting, so unless forced explicitly, in the expression

  (char *)&x[0]

the type of x is not changed as expected. So, to enforce the meaningful usage of the type-casting, we need to enclose it into extra par of parenthesis.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261