-1

i saw this question at my c language final exam and the output is 513 and i don't know why

#include <stdio.h>
int main(void){
    char a[4] = {1,2,3,4};
    print("%d" , *(short*)a);
}
Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
hero1780
  • 23
  • 3
  • 3
    Time to learn about bits, computer words, how longer data-types are stored on your system, and about [*endianness*](https://en.wikipedia.org/wiki/Endianness). – Some programmer dude Jun 14 '19 at 13:38
  • 3
    What value do you *think* it would print, and why? – abelenky Jun 14 '19 at 13:40
  • 3
    @hero1780 In general the code has undefined behavior because it is not necessary that the character array is aligned as a short number. – Vlad from Moscow Jun 14 '19 at 13:40
  • 2
    I'm pretty sure this code has undefined because on some platforms it will just crash with a SIGBUS. – melpomene Jun 14 '19 at 13:40
  • What if the final exam question starts with, *"On our processor, in our classroom environment, assume this code is run....what is the output?"*? Now the behavior is no longer undefined; it is implementation specified. – abelenky Jun 14 '19 at 13:48
  • 1
    @abelenky How so? Do you know any compiler that documents a behavior for this code? – melpomene Jun 14 '19 at 13:56
  • in the exam it just says "what will it print when the given code block runs? " i did run it on my computer and the output is 513 @abelenky – hero1780 Jun 14 '19 at 14:24
  • In that case, @melpomene is correct: The code may put out anything or nothing, it may crash your computer or [erase your drive](https://blog.tchatzigiannakis.com/undefined-behavior-can-literally-erase-your-hard-disk/). The best you can say is that the output ***might reasonably*** be `513`; but it could be anything. – abelenky Jun 14 '19 at 14:27

3 Answers3

7

Your array of bytes is (in hex):

[ 0x01, 0x02, 0x03, 0x04 ]

If you treat the start of the array not as an array of bytes, but as the start of a short, then your short has value 0x01 0x02, and because your processor is "Little Endian", it reads backwards from how humans read it. We would it as 0x0201, which is the same as 513(Decimal)

abelenky
  • 63,815
  • 23
  • 109
  • 159
4

If the system this code is being run on meets the following requirements:

  • Unaligned memory access is permitted (or a is guaranteed to be short-aligned)

  • Little-endian byte order is used

  • sizeof(short) == 2

  • CHAR_BIT == 8

Then dereferencing a short * pointer to the following memory:

|  0x01  |  0x02  |  0x03  |  0x04  |

Will give you 0x0201, or 513 in base 10.

Also, do note that even if all these requirements are met, aliasing a char [] array as a short * violates the strict aliasing rule.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85
  • 1
    The code also requires unaligned access to integers (or a compiler that aligns `a` on a two-byte boundary). The format specifier is fine: `short` is implicitly converted to `int` when passed to a varargs function. – melpomene Jun 14 '19 at 13:58
  • 2
    I would also add something about using `-fno-strict-aliasing`, since this is an aliasing violation regardless of alignment. – Christian Gibbons Jun 14 '19 at 14:03
  • @melpomene *The format specifier is fine: short is implicitly converted to `int` when passed to a varargs function.* A bit late here, but that format specifier does have problems, as the promotion of `short` to `int` might very well sign extend the `short`. – Andrew Henle Feb 07 '20 at 14:45
1

The code casts your char* pointer into short* one and prints its value.

short in C is represented in 2 bytes, and the binary representation of the first two bytes of your array is 00000001 00000010 but because the processor is a little endian one it reads it as 00000010 00000001 which is 513 in decimal.

  • `short` in C must be at least 16 bits, but it may be more than two bytes. It can even be one byte in an implementation in which a byte is at least 16 bits. It is not true that it is necessarily two bytes. – Eric Postpischil Jun 14 '19 at 15:09