Historically, program code and other sections were loaded starting at address 0x0 (this is also basic human nature). Therefore, to give the stack as much room as possible to grow without conflicting with these other sections, it was placed at the opposite end of memory and grows downwards. The end.
Yes. Here is a short program to discover this for yourself.
	int main(void) {
		unsigned int a = 0xffffffff;
		a >>= 1;
		return 0;
	}
And here is the way to print formatted strings in gdb.
(gdb) printf "%x\n", a
7fffffff
>> operator, and vice versa?
No, little-endian processors handle left-shift and right-shift correctly in hardware, so that programmers don't have to think about the number representation. Here is the disassembly of the program above to demonstrate this:
Dump of assembler code for function main:
0x00001fe6 <main+0>	push   %ebp
0x00001fe7 <main+1> 	mov    %esp,%ebp
0x00001fe9 <main+3> 	sub    $0x18,%esp
0x00001fec <main+6> 	movl   $0xffffffff,-0xc(%ebp)
0x00001ff3 <main+13> 	lea    -0xc(%ebp),%eax
0x00001ff6 <main+16> 	shrl   (%eax)
0x00001ff8 <main+18> 	mov    $0x0,%eax
0x00001ffd <main+23> 	leave  
0x00001ffe <main+24> 	ret    
End of assembler dump.
Compiling Loops
#include <stdio.h>
int main(void) {
	int i, total;
	total = 1;
	for (i = 0; i < 10; i++) {
		total = total * 2;
	}
	printf("%d\n", total);
	return 0;
}
gcc on Mac OS X produces the following disassembly (using gdb).
Dump of assembler code for function main:
0x00001fae <main+0> 	push   %ebp 0x00001faf <main+1> 	mov    %esp,%ebp 0x00001fb1 <main+3> 	push   %ebx 0x00001fb2 <main+4> 	sub    $0x24,%esp 0x00001fb5 <main+7> 	call   0x1fba <main+12> 0x00001fba <main+12> 	pop    %ebx 0x00001fbb <main+13> 	movl   $0x1,-0xc(%ebp) 0x00001fc2 <main+20> 	movl   $0x0,-0x10(%ebp) 0x00001fc9 <main+27> 	jmp    0x1fd5 <main+39> Jump to test in the middle 0x00001fcb <main+29> 	lea    -0xc(%ebp),%eax Loop beginning 0x00001fce <main+32> 	shll   (%eax) Loop body 0x00001fd0 <main+34> 	lea    -0x10(%ebp),%eax 0x00001fd3 <main+37> 	incl   (%eax) Loop update 0x00001fd5 <main+39> 	cmpl   $0x9,-0x10(%ebp) Loop test 0x00001fd9 <main+43> 	jle    0x1fcb <main+29> Conditional jump to loop beginning 0x00001fdb <main+45> 	mov    -0xc(%ebp),%eax 0x00001fde <main+48> 	mov    %eax,0x4(%esp) 0x00001fe2 <main+52> 	lea    0x41(%ebx),%eax 0x00001fe8 <main+58> 	mov    %eax,(%esp) 0x00001feb <main+61> 	call   0x3005 <dyld_stub_printf> 0x00001ff0 <main+66> 	mov    $0x0,%eax 0x00001ff5 <main+71> 	add    $0x24,%esp 0x00001ff8 <main+74> 	pop    %ebx 0x00001ff9 <main+75> 	leave   0x00001ffa <main+76> 	ret     
End of assembler dump.
Procedure Calls and Stack Frames
Here is a simple program that will allow us to examine the locations of
function arguments and return values.
#include <stdio.h>
int func(int a, int b) {
	return a+b;
}
int main(void) {
	int d = func(22,33);
	printf("%d\n", d);
	return 0;
}
Here is the disassembly of the main and func functions
in gdb.
Dump of assembler code for function func:
0x00001faa <func+0>  	push   %ebp 0x00001fab <func+1>>  	mov    %esp,%ebp 0x00001fad <func+3>>  	sub    $0x8,%esp 0x00001fb0 <func+6>>  	mov    0xc(%ebp),%eax 0x00001fb3 <func+9>>  	add    0x8(%ebp),%eax 0x00001fb6 <func+12>>  	leave   0x00001fb7 <func+13>>  	ret  
End of assembler dump.
This is what the call stack looks like by line func+3.
%ebp+12 a = 22 %ebp+8 b = 33 %ebp+4 return address = 0x00001fd9 %ebp old %ebp = 0xbffff338 %ebp-4   %ebp-8 == %esp, from the instruction at func+3 above 
The return value a+b is placed into the %eax register.
You can also use the print command in gdb to call functions and
display their return values.
anti-hero-1:sections buy-ppham$ gdb call
GNU gdb 6.3.50-20050815 (Apple version gdb-966) (Tue Mar 10 02:43:13 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin"...Reading symbols for shared libraries ... done
(gdb) start
Breakpoint 1 at 0x1fc3: file call.c, line 9.
Starting program: /Users/buy-ppham/src/CSE351/sections/call 
funReading symbols for shared libraries ++. done
Breakpoint 1, main () at call.c:9
9		int d = func(22,33);
(gdb) print func(11,22)
$1 = 33
(gdb) print func(33,44)
$2 = 77
(gdb) 
Arrays
Where do local arrays get stored? Here's a program that will let us find out!
#include <stdio.h>
int* arrayfunc(int i, int j) {
	int array[10][10];
	int x;
	printf("Address of array: %x\n", array);
	printf("Address of x: %x\n", &x);
	printf("Address of array[%d][%d]: %x\n", i, j, &array[i][j]);
}
	
int main(void) {
	arrayfunc(2,3);
}
Compiling and running this program gives us:
anti-hero-3:sections buy-ppham$ gcc -o arrays -g arrays.c
anti-hero-3:sections buy-ppham$ ./arrays
Address of array: bffff220
Address of x: bffff21c
Address of array[2][3]: bffff27c
Using a hex calculator, you can discover that the difference between the
beginning of the array and array[2][3] is 92 bytes.
Divide 92 by 4, because the size of an int is 4 bytes, and you get 23.
This is the expected offset since each row of the array contains 10 items.
23 = (2*10) + 3