As an example of the differences, this is x86 assembly created using gcc 4.4 with -O3
int arithmetic0 ( int aValue )
{
return aValue / 2;
}
00000000 <arithmetic0>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 8b 45 08 mov 0x8(%ebp),%eax
6: 5d pop %ebp
7: 89 c2 mov %eax,%edx
9: c1 ea 1f shr $0x1f,%edx
c: 8d 04 02 lea (%edx,%eax,1),%eax
f: d1 f8 sar %eax
11: c3 ret
int arithmetic1 ( int aValue )
{
return aValue >> 1;
}
00000020 <arithmetic1>:
20: 55 push %ebp
21: 89 e5 mov %esp,%ebp
23: 8b 45 08 mov 0x8(%ebp),%eax
26: 5d pop %ebp
27: d1 f8 sar %eax
29: c3 ret
int arithmetic2 ( int aValue )
{
return aValue * 2;
}
00000030 <arithmetic2>:
30: 55 push %ebp
31: 89 e5 mov %esp,%ebp
33: 8b 45 08 mov 0x8(%ebp),%eax
36: 5d pop %ebp
37: 01 c0 add %eax,%eax
39: c3 ret
int arithmetic3 ( int aValue )
{
return aValue << 1;
}
00000040 <arithmetic3>:
40: 55 push %ebp
41: 89 e5 mov %esp,%ebp
43: 8b 45 08 mov 0x8(%ebp),%eax
46: 5d pop %ebp
47: 01 c0 add %eax,%eax
49: c3 ret
int arithmetic4 ( int aValue )
{
return aValue / 4;
}
00000050 <arithmetic4>:
50: 55 push %ebp
51: 89 e5 mov %esp,%ebp
53: 8b 55 08 mov 0x8(%ebp),%edx
56: 5d pop %ebp
57: 89 d0 mov %edx,%eax
59: c1 f8 1f sar $0x1f,%eax
5c: c1 e8 1e shr $0x1e,%eax
5f: 01 d0 add %edx,%eax
61: c1 f8 02 sar $0x2,%eax
64: c3 ret
int arithmetic5 ( int aValue )
{
return aValue >> 2;
}
00000070 <arithmetic5>:
70: 55 push %ebp
71: 89 e5 mov %esp,%ebp
73: 8b 45 08 mov 0x8(%ebp),%eax
76: 5d pop %ebp
77: c1 f8 02 sar $0x2,%eax
7a: c3 ret
int arithmetic6 ( int aValue )
{
return aValue * 8;
}
00000080 <arithmetic6>:
80: 55 push %ebp
81: 89 e5 mov %esp,%ebp
83: 8b 45 08 mov 0x8(%ebp),%eax
86: 5d pop %ebp
87: c1 e0 03 shl $0x3,%eax
8a: c3 ret
int arithmetic7 ( int aValue )
{
return aValue << 4;
}
00000090 <arithmetic7>:
90: 55 push %ebp
91: 89 e5 mov %esp,%ebp
93: 8b 45 08 mov 0x8(%ebp),%eax
96: 5d pop %ebp
97: c1 e0 04 shl $0x4,%eax
9a: c3 ret
The divisions are different - with a two's complement representation, shifting a negative odd number right one results in a different value to dividing it by two. But the compiler still optimises the division to a sequence of shifts and additions.
The most obvious difference though is that this pair don't do the same thing - shifting by four is equivalent to multiplying by sixteen, not eight! You probably would not get a bug from this if you let the compiler sweat the small optimisations for you.
aNumber = aValue * 8;
aNumber = aValue << 4;