Проблема с инициализацией констедов
Вопрос
Этот код, когда скомпилирован в XLC 8.0 (на AIX 5.3), создает неправильный результат. Это должно распечатать 12345
, но вместо печатается 804399880
Отказ Удаление const
спереди result
Заставляет код работать правильно.
Где ошибка?
#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;
}
Команда компиляции:
/usr/vacpp/bin/xlC example.cpp -g
Редактировать: Изменение строки формата Printf выше на «% ld n» не помогает. Редактировать 2: используемая версия AIX была 5,3, а не 6.1.
Решение
XLC 10.0 работает нормально, кажется, авторская ошибка компилятора
Другие советы
Это помечено C ++, так что происходит при использовании Cout вместо printf?
Похоже, что проблема в том, что вы говорите Printf напечатать unsigned int, а затем отправляя его подписанным долгом, чтобы на самом деле печатать. Скорее всего, планировка памяти отличается, и printf не может понять, что вы действительно хотели сделать.
Это будет немного догадаться, почему Const имеет значение, но можно сделать разумное предположение.
Переменные с помощью блока сферы, такие как result
можно выделить в реестр или положить в стек. Есть много факторов, которые влияют на, используется ли реестр. Это вполне возможно, что const
Вопросы в этом случае. В конце концов, это компиляторы правильно использовать то, что он думает, работает лучше всего.
Аналогичным образом, аргументы для функций могут быть переданы в регистры или на стеке. В качестве функций часто скомпилированы отдельно, их интерфейс (т. Е. Декларация) диктует, какой аргумент идет где. Printf (...) - это особый случай, поскольку его можно назвать с разными типами аргументов. В результате, какие данные заканчиваются, где будет варьироваться, и вам нужно сказать Printf (...) Что ожидать.
Теперь при прохождении переменной к функции компилятор обычно должен копировать его. Из реестра в стек один регистрируйся в другой, Etcetera, возможно, возможна довольно много вариаций. Как я уже указывал, местоположение источника может отличаться в зависимости от наличия или отсутствия const
.
Теперь, как это происходит, вы передаете неправильный спецификатор формата printf(...)
, а именно %u
вместо %ld
. Отказ Это может привести к печати (...), чтобы посмотреть в неправильном месте, чтобы получить его данные - возможно в регистре вместо стека или наоборот. Такое действие может вызвать довольно удивительные результаты. printf(...)
может, например, наткнуться на ваш неисправный result
, или случайные старые значения в некоторых регистре. Похоже, что в случае, не в том случае, если это произойдет правильное значение (даже если это могло найти его в неправильном месте), тогда как в корпусе Const printf(...)
просто находит мусор.
Вероятно, не связан, но будьте осторожны: спецификатор% U для printf указывает на беззнаковую целое число, но вы передаете подписанное целое число.
G ++ обрабатывает это просто хорошо и не упоминает предупреждение. Это жалуется на printf. Вы должны использовать% LU для длинного int. Или еще лучше, используя% ld или литья, чтобы (unsigned long int).