Resultado do concurso para ganhar o convite VIP
- por Sergio Prado
Gostaria de agradecer a todos que participaram do concurso para concorrer a um convite VIP para o Seminário C&C++ para Sistemas Embarcados 2010, que será realizado na próximo sábado (06 de novembro).
O objetivo da questão proposta era mostrar que uma sutil diferença entre a declaração de uma variável com signed ou unsigned pode fazer toda a diferença em uma simples expressão condicional.
Dos 27 participantes, 10 acertaram na resposta e na justificativa. Considerei como corretas todas as respostas que indicavam que o LED seria ou poderia ser apagado.
Alguns foram mais além, como o Henrique Pérsico Rossi, que considerou acertadamente que a implementação de um “char” é depedente do compilador, e não do padrão ANSI-C. Ou seja, para determinados compiladores, char é como padrão “signed char”, mas para outros pode ser “unsigned char”.
O Daniel Moreira Cestari também fez um comentário interessante, indicando que o tamanho da palavra da CPU pode influenciar no resultado, por exemplo, se o tamanho do int tiver o mesmo tamanho do char.
Para fazer o sorteio, numerei os acertadores de 1 a 10, e utilizei o método “Grito à distância para a esposa na sala”…) Pedi para ela escolher um número de 1 a 10, e ela escolheu o número 5, o Fernando Almeida. Parabéns Fernando!
Mas quem não ganhou o convite, não deixe de participar do evento. As inscrições vão até amanhã (03/11).
Como gostei bastante da resposta do Henrique, segue-a abaixo na integra:
/*************************************************/
Resposta: Depende!
Se o compilador implementar char como sendo do tipo signed (por padrão)…Não Acende! Se o compilador implementar char como sendo do tipo unsigned…Acende! Ou seja, é IMPLEMENTATION DEFINED.
Antes que uma operação aritmética seja executada, algumas conversões implícitas ocorrem ao longo do seu processamento. Uma delas é “balancing convertion”, a qual garante que todos operandos de uma operação sejam convertidos para um tipo em comum para que a operação possa ser executada. No entanto, para que esta conversão ocorra, faz-se necessária uma nova conversão implícita, integral promotion. Todos os valores do tipo short, char, enum e bit-field (conhecidos como small integer types) são convertidos para um dos seguintes tipos:
1) signed int, caso este tipo consiga representar o valor do tipo original (seja short, char, enum ou bit-field), ou
2) unsigned int, caso contrário.
Bem, dado o conceito acima, vamos aplicá-lo ao exercício proposto.
O compilador encontra os seguintes códigos:
1) chamada à função setLedStatus( LED_ON ) – O valor LED_ON (igual a 0xFF) é convertido para o tipo char, seja ele signed ou unsigned. Este processo é chamado de assigning convertion. Como char tem o tamanho de 1 byte, até aqui…sem problemas!
2) teste condicional if ( status == LED_ON ) – Aqui aparece o problema! Dado que um operador relacional é encontrado (==, mas poderia ser !=, >, <, >=, <=, ou qualquer outro operador binário ou ternário), as regras de balancing convertion, como mencionado acima, são seguidas.
2.1) status poder ser convertido para int? Sim, pois trata-se de um tipo char. status é signed ou unsigned (lembre-se, implementation defined)? Vamos considerar uma arquitetura de 32 bits.
– se for signed: status assume o valor 0xFFFFFFFF, para continuar a representar o valor passado como argumento, -1 (value preserving em ação!)
– se for unsigned: status assume o valor 0x000000FF, para continuar a representar o valor passado como argumento, 255 (value preserving em ação!)
2.2) 0xFF é convertido para int. Considerando uma arquitetura de 32 bits, este valor é convertido para 0x000000FF.
Solução final:
1) se char for signed: if ( 0xFFFFFFFF == 0x000000FF ) => FALSE, portando NÃO ACENDE LED!!
2) se char for unsigned: if ( 0x000000FF == 0x000000FF ) => TRUE, portando ACENDE LED!!
/*************************************************/
Um abraço!
Sergio Prado