Em sistemas unix, se um arquivo é executável ou não depende somente de suas permissões, não de seu nome ou de seu conteúdo. (Se o formato do arquivo não for um executável válido, o sistema tentará executá-lo e tratá-lo como um dos possíveis erros ao executar um programa, juntamente com recursos insuficientes, bibliotecas ausentes, etc.)
A maioria dos arquivos baixados da Web não deve ser executável, portanto, o curl não tenta tornar o arquivo executável. Mesmo que o arquivo tenha sido executado, talvez você não queira executá-lo agora; por exemplo, você pode querer revisá-lo e tornar o arquivo executável apenas se ele passar no seu comentário.
Por outro lado, o gcc ou qualquer outro compilador pretende produzir um programa executável, portanto, não é de surpreender que ele execute as etapas necessárias. Com o gcc, este é um dos últimos estágios do processo de compilação. Você pode observá-lo com strace :
$ strace -f gcc a.c
…
23429 execve("/usr/bin/ld", ["/usr/bin/ld", "--eh-frame-hdr", "-m", "elf_i386", "--hash-style=both", "-dynamic-linker", "/lib/ld-linux.so.2", "-z", "relro", "/usr/lib/gcc/i486-linux-gnu/4.3."..., "/usr/lib/gcc/i486-linux-gnu/4.3."..., "/usr/lib/gcc/i486-linux-gnu/4.3."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/usr/lib/gcc/i486-linux-gnu/4."..., "-L/lib/../lib", ...], [/* 82 vars */]) = 0
…
23429 chmod("a.out", 0755) = 0
23429 exit_group(0) = ?
…
Em outras palavras, o linker , que é o último estágio da compilação e produz o executável , altera as permissões no arquivo de saída para que seja executável como sua última etapa.