Pergunta
Este código, quando compilado em xlC 8.0 (no AIX 5.3), produz o resultado errado.Deveria imprimir 12345
, mas em vez disso imprime 804399880
.Removendo o const
em frente de result
faz o código funcionar corretamente.
Onde está o bug?
#include <stdio.h>
#include <stdlib.h>
#include <string>
long int foo(std::string input)
{
return strtol(input.c_str(), NULL, 0);
}
void bar()
{
const long int result = foo("12345");
printf("%u\n", result);
}
int
main()
{
bar();
return 0;
}
Comando de compilação:
/usr/vacpp/bin/xlC example.cpp -g
Editar:Alterar a string de formato printf acima para "%ld " não ajuda.Editar 2:A versão do AIX usada foi 5.3, não 6.1.
Solução
XLC 10.0 funciona bem, parece ser um bug do compilador
Outras dicas
Isso é marcado C ++, então o que acontece quando você usa o cout em vez de printf?
Parece que o problema é que você está dizendo ao PrintF para imprimir um Int não assinado e, em seguida, enviando um INT assinado muito para realmente imprimir. Provavelmente, o layout da memória é diferente e o printf não consegue entender o que você realmente queria fazer.
Será um pouco difícil adivinhar por que const é importante, mas pode-se fazer uma suposição razoável.
Variáveis com escopo de bloco, como result
pode ser alocado em um registrador ou colocado na pilha.Existem muitos fatores que influenciam a utilização de um registro.É bem possível que const
importa, neste caso.No final das contas, o compilador está certo em usar o que acha que funciona melhor.
Da mesma forma, argumentos para funções podem ser passados em registradores ou na pilha.Como as funções são frequentemente compiladas separadamente, sua interface (ou seja,declaração) determina qual argumento vai para onde.printf(...) é um caso especial, pois pode ser chamado com argumentos de diferentes tipos.Como resultado, quais dados vão parar onde irão variar, e você precisa dizer ao printf(...) o que esperar.
Agora, ao passar uma variável para uma função, o compilador geralmente precisa copiá-la.De um registro para a pilha, de um registro para outro, etc., existem algumas variações possíveis.Como indiquei, o local de origem pode diferir dependendo da presença ou ausência de const
.
Agora, acontece que você passa o especificador de formato errado para printf(...)
, nomeadamente %u
em vez de %ld
.Isso pode fazer com que printf(...) procure no lugar errado para obter seus dados - talvez em um registro em vez da pilha, ou vice-versa.Tal ação pode causar resultados bastante surpreendentes. printf(...)
poderia, por exemplo, tropeçar em seu não copiado result
, ou os valores antigos aleatórios em algum registro.Parece que no caso não-const ele encontra o valor correto (mesmo que possa tê-lo encontrado no lugar errado), enquanto no caso const printf(...)
apenas encontra lixo.
Provavelmente não está relacionado, mas tenha cuidado: o especificador %U para Printf indica um número inteiro não assinado, mas você está passando por um número inteiro assinado.
O G ++ lida com isso muito bem e não menciona um aviso. Ele reclama de printf. Você deve estar usando %Lu por um Int longo. Ou melhor ainda, usando %LD ou fundição para (não assinado Long Int).