## C Puzzle #3

What is the output of the following programm?

#include<stdio.h>

int main() {
printf("%i\n", -13>>1);
}

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

-7

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 speciﬁed by
an immediate value and stores the quotient in that byte, word, or long respectively.
The second variation right shifts by a count value speciﬁed in the CL register. sar
rounds toward negative inﬁnity; the high-order bit remains unchanged.

This means, 1111.1111.1111.1111.1111.1111.1111.1001 is correct. And that’s -7.

You can skip to the end and leave a response. Pinging is currently not allowed.

### 2 Responses to “C Puzzle #3”

1. Stefan Koch says:

I’m always a bit confused by compilers stack management. Why does the compiler subtract 16 from %esp, but then use only 4(%esp) with a four byte value. I mean it’ll only reach %esp to 7(%esp) with the .LC0 mark and the integer, so the top part 8(%esp) to 15(%esp) will be lost during the call.

2. _djh says:

Wrong. It’s implementation defined.

C++11 Standard, 5.8 and/or C99 Standard, 6.5.7:

“The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2 . If E1 has a signed type and a negative value, the resulting value is implementation-defined.”