Проблема с инициализацией Consts - PullRequest
1 голос
/ 15 апреля 2010

Этот код при компиляции в 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.

Ответы [ 5 ]

3 голосов
/ 15 апреля 2010

xlC 10.0 работает нормально, похоже, ошибка компилятора

2 голосов
/ 15 апреля 2010

Это тег c ++, что происходит, когда вы используете cout вместо printf?

Похоже, проблема в том, что вы говорите printf напечатать int без знака, а затем отправляете ему длинное int со знаком для фактической печати. Скорее всего, структура памяти отличается, и printf не может понять, что вы на самом деле хотели сделать.

1 голос
/ 15 апреля 2010

Будет немного догадываться, почему const имеет значение, но можно сделать разумное предположение.

Переменные с областью действия блока, такие как result, могут быть размещены в регистре или помещены в стек. Есть много факторов, которые влияют на то, используется ли регистр. Вполне возможно, что const имеет значение, в этом случае. В конце концов, это право компиляторов использовать то, что, по его мнению, работает лучше всего.

Аналогично, аргументы функций могут передаваться в регистрах или в стеке. Поскольку функции часто компилируются отдельно, их интерфейс (то есть объявление) определяет, какой аргумент идет куда. printf (...) является особым случаем, так как его можно вызывать с аргументами разных типов. В результате, какие данные в конечном итоге будут меняться, и вам нужно указать printf (...), чего ожидать.

Теперь при передаче переменной в функцию компилятор обычно должен ее скопировать. От регистра к стеку, от одного регистра к другому и т. Д., Существует довольно много возможных вариантов. Как я указывал, местоположение источника может отличаться в зависимости от наличия или отсутствия const.

Теперь, когда это происходит, вы передаете неправильный спецификатор формата printf(...), а именно %u вместо %ld. Это может привести к тому, что printf (...) будет искать неправильное место для получения своих данных - возможно, в регистре, а не в стеке, или наоборот. Такое действие может привести к довольно неожиданным результатам. printf(...) может, например, наткнуться на ваш не скопированный result или случайные старые значения в каком-то регистре. Кажется, что в неконстантном случае он находит правильное значение (даже если бы он нашел его в неправильном месте), тогда как в константном случае printf(...) просто находит мусор.

0 голосов
/ 15 апреля 2010

g ++ прекрасно справляется с этим и не упоминает предупреждение. Это жалуется на printf. Вы должны использовать% lu для длинного int. Или даже лучше, используя% ld или приведение к (unsigned long int).

0 голосов
/ 15 апреля 2010

Возможно, не связано, но будьте осторожны: спецификатор% u для printf указывает целое число без знака, но вы передаете целое число со знаком.

...