Ah, mas o problema não é com a manipulação de bits.
O problema foi provocado por scanf, que insiste em receber um ponteiro para um int (4 bytes), não para um char (1 byte).
Isso não pode ser detectado pelo compilador, porque ele é estúpido e não checa os argumentos do scanf ou do printf. Se você usasse uma ferramenta como o FlexeLint ( http://www.gimpel.com/html/flex.htm ) isso seria rapidamente verificado. )
No Dev-C++ esse problema realmente vai passar batido.
O que ocorreu foi o seguinte:
- O compilador gera código que checa se você escreveu algo fora dos limites do char (1 byte). Esse código consiste em inicializar a pilha com um valor conhecido e fixo.
Como variáveis locais são armazenadas na pilha do processador, então, mesmo que a variável deva ocupar apenas 1 byte, o compilador reserva 8 bytes para ela, porque a pilha é melhor acessada de 8 em 8 bytes (o processador, internamente, mesmo em x86, trabalha em 64 bits, daí preferir essa divisão artificial de 8 bytes).
- Você chamou scanf com o endereço da variável char, e então você preencheu não só a variável char (1 byte), mas também 3 bytes que vêm depois dessa variável, porque na verdade o scanf espera um ponteiro para int, não char.
- Quando o programa saiu, ele chamou código que checa se a pilha está comprometida. Como foi visto que os 3 bytes na pilha foram modificados indevidamente, então ele provocou o tal erro.
Para consertar esse problema:
- Passe o endereço de uma variável int para o scanf.
ou
- Em vez de usar scanf (argh - ugh - uff - bleargh) leia as linhas com gets mesmo, e use atol ou atoi para efetuar as conversões.
E de qualquer maneira, não economize memória desse jeito (usando variáveis char), a menos que você saiba o que está fazendo. Usar o padrão - int - usa até menos memória porque as instruções do processador que lidam com os registradores completos (em 32 bits, EAX, EBX, ECX etc. e em 64 bits, RAX, RBX, etc.) são menores que as instruções que lidam com pedaços de um registrador, ou bytes.