1

I have to do a small assignment for school. I am writing this in C. The question is:

Given

uint16_t A[] = { 0xabce, 0x43fe, 0xcf54, 0xffff };
uint8_t *p = (uint8_t *)&A[0];

What is the value of p[3]?

I did some research and found that the numbers will be put back into my computer using little-endian. So

p[] = {171, 67, 207, 255}

However, when I print p[] I get

p[0] = 206
p[1] = 171
p[2] = 254
p[3] = 67

I am very confused by this, can anyone please tell me why this is happening?

e0k
  • 6,961
  • 2
  • 23
  • 30
LvanRooij
  • 86
  • 7
  • 1
    You are aware right that `p[0]` and `p[1]` will both point to separate bytes of A[0]? – Fantastic Mr Fox Feb 25 '16 at 22:23
  • Casting pointers does no conversion. `p[0]` is the first byte of `A[0]`, `p[1]` the second byte of `A[0]`, `p[2]` is the first bytes of `A[1]`, etc. – Colonel Thirty Two Feb 25 '16 at 22:26
  • `uint8_t` is not a character type, therefore this is undefined behavior. – EOF Feb 25 '16 at 22:32
  • @ColonelThirtyTwo thanks! I get it now – LvanRooij Feb 25 '16 at 22:34
  • @Ben, thanks dude! I get it now, pretty simple actually :D – LvanRooij Feb 25 '16 at 22:34
  • @EOF It may be a character type, and usually is – M.M Feb 25 '16 at 22:41
  • @M.M How can a `uint8_t` not be a character type? Is that a type only concern as it certainly must have the same range and size of `unsigned char`? – chux - Reinstate Monica Feb 25 '16 at 23:04
  • @chux it could be an extended integer type , in theory – M.M Feb 25 '16 at 23:05
  • @M.M Hmmm do you mean like `unsigned char` is `16-bit` and `uin8_t` is 8-bit? Does not `sizeof()` need to work, even for extended integer types? `sizeof(unsigned char)` must be 1. and `uint8_t` has no padding. So I can't see it working "in theory". (No need to reply as this is getting far off OP's post.) – chux - Reinstate Monica Feb 25 '16 at 23:13
  • @chux that situation isn't possible - there cannot be any type smaller than `char`. Not sure what was unclear about my previous comment? `char` and `uint8_t` would both be 8-bit, however the first would be a character type and the second would be an unsigned integer type (actually a typedef for an unsigned integer type, since `uintN_t` must be a typedef) – M.M Feb 25 '16 at 23:15
  • "unsigned char" and "uint8_t" are one and the same data type as far as the computer is concerned. The later is created as a semantic help to remind the developer that those values should not be treated as text - One could, theoretically have a computer architecture and compiler where the char data type would be different from 8bit, but that would simply make most C programs fail - while a program using `uint8_t` would still work. – jsbueno Feb 25 '16 at 23:22
  • Also, it is 2016, and one should not assume each text character is always 1 byte (8 bit) wide. Programs behaving this way as plain, simply, incorrect. For dealing with text in C, one needs a higher level library, or system functions, that are aware of character encodings. For more information, read http://www.joelonsoftware.com/articles/Unicode.html – jsbueno Feb 25 '16 at 23:24
  • @jsbueno The first sentence of your comment is not guaranteed by the C Standard although it is a common way that compilers implement uint8_t. The situation of `char` not being 8-bit but `uint8_t` working is forbidden by the C Standard. – M.M Feb 25 '16 at 23:34

1 Answers1

3

So, jsut to be clear - in a little endian machinne, this declaration:

uint16_t A[] = { 0xabce, 0x43fe, 0xcf54, 0xffff };

Will but these bytes in order, in your memory:

ce | ab | fe | 43 | 54 | cf | ff | ff |

(In decimal):

206|171 |254 | 67 | 84 | 207| 255| 255|

So, when you tell the compiler that starting at the very same position in memory, you can read numbers that are one byte long, what is retrievable in your "p" vector are the 8 numbers above.

uint8_t *p = (uint8_t *)&A[0];

(Which could also be written simply uint8_t *p = (uint8_t *)A;)

Keep in mind that in C, it is the developer's task to know how long a vector is. In this example, it might be that one would have the convention that the number "0xffff" would end the 16bit sequence, for example. Either way, you have twice that number of elements to read as 8 bit.

jsbueno
  • 99,910
  • 10
  • 151
  • 209