Search code examples
cpointerschar

Why does following C code print 45 in case of int 45 and 36 in case of STRING and ASCII value of CHAR?


struct s{
int a;
char c;
};
int main()
{
    struct s b = {5,'a'};
    char *p =(char *)&b;
    *p = 45;
    printf("%d " , b.a);
    return 0;
}

If *p is changes to any character than it prints ASCII value of character , if *p changed to any string ("xyz") than it prints 36 . Why it's happening ?

Can you give memory map of structure s and *p ?

According to me mamory of struct

s as z-> (****)(*) assuming 4 byte for int . and when s initialize than it would have become (0000000 00000000 00000000 00000101)(ASCII OF char a) and *p points to starting address of z . and *p is a character pointer so it will be store ASCII value at each BYTE location i.e. at each * will be occupied by ASCII of char . But now we make it to 45 so z would have become (45 0 0 5 )(ASCII of char a) . But it's not true why ?


Solution

  • When you write to the struct through a char * pointer, you store 45 in the first byte of the struct. If you are on a Little-Endian implementation, you will write to the low end of b.a. If you are on a Big-Endian implementation, you will write to the high end of b.a.

    Here is a visualization of what typically happens to the structure on an implementation with 16-bit ints, before and after the assignment *p=45. Note that the struct is padded to a multiple of sizeof(int).

    Little-Endian

    Before:  a [05][00]  (int)5
             c [61]
               [  ]
    
    After:   a [2d][00]  (int)45
             c [61]
               [  ]
    

    Big-Endian

    Before:  a [00][05]  (int)5
             c [61]
               [  ]
    
    After:   a [2d][05]  (int)11525
             c [61]
               [  ]
    

    With larger ints, there are more ways to order the bytes, but you are exceedingly unlikely to encounter any other that the two above in real life.

    However, The next line invokes undefined behaviour for two reasons:

    printf("%d " , b.a);
    
    1. You are modifying a part of b.a through a pointer of a different type. This may give b.a a "trap representation", and reading a value containing a trap representation causes undefined behaviour. (And no, you are not likely to ever encounter a trap representation (in an integer type) in real life.)
    2. You are calling a variadic function without a function declaration. Variadic functions typically have unusal ways of passing arguments, so the compiler has to know about it. The usual fix is to #include <stdio.h>.

    Undefined behaviour means that anything could happen, such as printing the wrong value, crashing your program or (the worst of them all) doing exactly what you expect.