Why This program is not showing any segmentation fault in 32 bit system ?
Look, this is slightly simplified your program:
1       int main(int argc, char *argv[])
2       {
3         char name[100];
4         unsigned int len = 3;
5         name[len-argc] = 1;
6         return 0;
7       }
So when I build it as 32-bit program gcc -m32 -g main.c -o main32 this is how under gdb the address space of a process looks:
$ gdb -q --args ./main32 1 2 3
Reading symbols from /home/main32...done.
(gdb) start
(gdb) info proc mappings
process 28330
Mapped address spaces:
        Start Addr   End Addr       Size     Offset objfile
          0x110000   0x111000     0x1000        0x0 [vdso]
          0x3fa000   0x418000    0x1e000        0x0 /lib/ld-2.12.so
          0x418000   0x419000     0x1000    0x1d000 /lib/ld-2.12.so
          0x419000   0x41a000     0x1000    0x1e000 /lib/ld-2.12.so
          0x41c000   0x5a8000   0x18c000        0x0 /lib/libc-2.12.so
          0x5a8000   0x5aa000     0x2000   0x18c000 /lib/libc-2.12.so
          0x5aa000   0x5ab000     0x1000   0x18e000 /lib/libc-2.12.so
          0x5ab000   0x5ae000     0x3000        0x0
         0x8048000  0x8049000     0x1000        0x0 /home/main32
         0x8049000  0x804a000     0x1000        0x0 /home/main32
        0xf7fdf000 0xf7fe0000     0x1000        0x0
        0xf7ffd000 0xf7ffe000     0x1000        0x0
        0xfffe9000 0xffffe000    0x15000        0x0 [stack]
(gdb) p/x &(name[len-argc])
$2 = 0xffffcfab
As you can see name[3-4] (it is underflow as you say) actually points to a valid address on stack. This is why your process does not crash.
When I build the same program as 64 bit (gcc -m64 -g main.c -o main64) the address will not be valid
(gdb) info proc mappings
process 29253
Mapped address spaces:
          Start Addr           End Addr       Size     Offset objfile
            0x400000           0x401000     0x1000        0x0 /home/main64
            0x600000           0x601000     0x1000        0x0 /home/main64
        0x3c40a00000       0x3c40a20000    0x20000        0x0 /lib64/ld-2.12.so
        0x3c40c1f000       0x3c40c20000     0x1000    0x1f000 /lib64/ld-2.12.so
        0x3c40c20000       0x3c40c21000     0x1000    0x20000 /lib64/ld-2.12.so
        0x3c40c21000       0x3c40c22000     0x1000        0x0
        0x3c41200000       0x3c41389000   0x189000        0x0 /lib64/libc-2.12.so
        0x3c41389000       0x3c41588000   0x1ff000   0x189000 /lib64/libc-2.12.so
        0x3c41588000       0x3c4158c000     0x4000   0x188000 /lib64/libc-2.12.so
        0x3c4158c000       0x3c4158d000     0x1000   0x18c000 /lib64/libc-2.12.so
        0x3c4158d000       0x3c41592000     0x5000        0x0
      0x7ffff7fdd000     0x7ffff7fe0000     0x3000        0x0
      0x7ffff7ffd000     0x7ffff7ffe000     0x1000        0x0
      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0 [vdso]
      0x7ffffffea000     0x7ffffffff000    0x15000        0x0 [stack]
  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]
(gdb) p/x &name[len-argc]
$5 = 0x8000ffffde3f
One more thing. This is how assembler looks for 64-bit  application:
(gdb) disassemble /m
Dump of assembler code for function main:
5         name[len-argc] = 1;
   0x0000000000400472 <+22>:    mov    -0x74(%rbp),%edx
   0x0000000000400475 <+25>:    mov    -0x4(%rbp),%eax
   0x0000000000400478 <+28>:    sub    %edx,%eax
   0x000000000040047a <+30>:    mov    %eax,%eax
=> 0x000000000040047c <+32>:    movb   $0x1,-0x70(%rbp,%rax,1)
This is $eax::
(gdb) p $eax
$1 = -1
But assigning use rax since you are in 64 mode. And this is the value of $rax:
(gdb) p/x $rax
$3 = 0xffffffff
So the program adds to a valid stack addres a huge positive offset and it results in invalid address.
I would like to underline that this is undefined behavior in both 32 and 64 modes. If you want to fix this undefined behavior you can read my another answer https://stackoverflow.com/a/24287919/184968.