1

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.

3
  • 1
    You need ((char *)&x)[0] etc. Commented Jan 1, 2017 at 7:33
  • You may also want to keep in mind you are using hex representation for negative numbers (your compiler should complain of overflow for type) given the types short and char (as opposed to unsigned short and unsigned char) in the event that is causing your confusion. Commented Jan 1, 2017 at 7:46
  • The code invokes undefined bahaviour. printf expects an unsigned int, you pass an int. Commented Jan 1, 2017 at 10:03

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

4 Comments

endianness? That's what you mean?
That does not change the undefined behaviour. printf expects an unsigned int, but the argument is int.
That can be addressed by converting all the int values to unsigned. For example (unsigned)(((char *)&x)[0]). It would probably be safer (at least, for human understanding) to use a union instead of relying solely on type conversions.
Yes, sorry, I mean endian-ness, not ended-ness. Humblest apologies. Error fixed.
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;

3 Comments

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).
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?
@SouravGhosh - The restriction was removed in C99 and onward. Only a warning for a possible trap is included, as well as a note that the result depends on the representation of the values.
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.