简体   繁体   中英

Output of the following C code

What will be the output of the following C code. Assuming it runs on Little endian machine, where short int takes 2 Bytes and char takes 1 Byte.

#include<stdio.h>
int main() {
    short int c[5];
    int i = 0;
    for(i = 0; i < 5; i++)
        c[i] = 400 + i;
    char *b = (char *)c;
    printf("%d", *(b+8));
    return 0;
}

In my machine it gave

-108

I don't know if my machine is Little endian or big endian. I found somewhere that it should give

148

as the output. Because low order 8 bits of 404(ie element c[4]) is 148. But I think that due to "%d", it should read 2 Bytes from memory starting from the address of c[4].

The code gives different outputs on different computers because on some platforms the char type is signed by default and on others it's unsigned by default. That has nothing to do with endianness. Try this:

    char *b = (char *)c;
    printf("%d\n", (unsigned char)*(b+8)); // always prints 148 
    printf("%d\n", (signed char)*(b+8));   // always prints -108 (=-256 +148)

The default value is dependent on the platform and compiler settings. You can control the default behavior with GCC options -fsigned-char and -funsigned-char .

To see what sizes types have in your system:

printf("char = %u\n", sizeof(char));    
printf("short = %u\n", sizeof(short));    
printf("int = %u\n", sizeof(int));    
printf("long = %u\n", sizeof(long));    
printf("long long = %u\n", sizeof(long long));  

Change the lines in your program

unsigned char *b = (unsigned char *)c;
printf("%d\n", *(b + 8));

And simple test (I know that it is not guaranteed but all C compilers I know do it this way and I do not care about old CDC or UNISYS machines which had different addresses and pointers to different types of data

printf(" endianes test: %s\n", (*b + (unsigned)*(b + 1) * 0x100) ==  400? "little" : "big");

Another remark: it is only because in your program c[0] == 400

c[4] stores 404 . In a two-byte little-endian representation, that means two bytes of 0x94 0x01 , or (in decimal) 148 1 .

b+8 addresses the memory of c[4] . b is a pointer to char , so the 8 means adding 8 bytes (which is 4 two-byte shorts). In other words, b+8 points to the first byte of c[4] , which contains 148 .

*(b+8) (which could also be written as b[8] ) dereferences the pointer and thus gives you the value 148 as a char . What this does is implementation-defined: On many common platforms char is a signed type (with a range of -128 .. 127 ), so it can't actually be 148 . But if it is an unsigned type (with a range of 0 .. 255 ), then 148 is fine.

The bit pattern for 148 in binary is 10010100 . Interpreting this as a two's complement number gives you -108 .

This char value (of either 148 or -108 ) is then automatically converted to int because it appears in the argument list of a variable-argument function ( printf ). This doesn't change the value.

Finally, "%d" tells printf to take the int argument and format it as a decimal number.

So, to recap: Assuming you have a machine where

  • a byte is 8 bits
  • negative numbers use two's complement
  • short int is 2 bytes

... then this program will output either -108 (if char is a signed type) or 148 (if char is an unsigned type).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM