What is the output of the following programm?
#include<stdio.h>
int main() {
printf("%i\n", -13>>1);
}
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Short answer
-7
Long answer
Signed integers are two’s complement binary values that can be used to represent both positive and negative integer values.
Source: Intels IA-32 Architectures Software Developer's Manuals, page 83
When you want to get the two's complement representation of -13, you have to get the binary representation of 13, invert the digits and add one. As 13 is 1101 in binary, -13 looks like this on a 32 bit machine: 1111.1111.1111.1111.1111.1111.1111.0011
So two results might be logical: 0111.1111.1111.1111.1111.1111.1111.1001
or
1111.1111.1111.1111.1111.1111.1111.1001
Lets get the assembly code:
gcc -S -O0 test.c
.file "test.c"
.section .rodata
.LC0:
.string "%i\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $16, %esp
movl $-7, 4(%esp)
movl $.LC0, (%esp)
call printf
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2"
.section .note.GNU-stack,"",@progbits
In line 18 you can see that the bitshift already happened. When you introduce a variable for a
, you can see that the compiler makes use of the assembly command sarl %eax
or sarl $2, %eax
when you shift by two.
When you take a look at Oracles IA-32 Assembly Language Reference Manual, page 56, you find:
sar right shifts (signed divides) a byte, word, or long value for a count specified by an immediate value and stores the quotient in that byte, word, or long respectively. The second variation right shifts by a count value specified in the CL register. sar rounds toward negative infinity; the high-order bit remains unchanged.
This means, 1111.1111.1111.1111.1111.1111.1111.1001 is correct. And that's -7.