Каков вывод этой программы? - PullRequest
0 голосов
/ 07 октября 2009

, когда я пытался запустить компиляцию и выполнить этот оператор в простом файле c:

main(){ printf("%d");}

на HP это дает мне 64, а на AIX - 804359524.

Может ли кто-нибудь сказать мне, что это за поведение.

Ответы [ 5 ]

21 голосов
/ 07 октября 2009

Полагаю, вы имеете в виду:

int main()
{
  printf("%d");
}

В этом случае printf () читает int (как указано спецификатором формата% d) из стека. Поскольку вы не указали один, он просто читает все, что находится в стеке, и использует это. Следовательно, вы видите псевдослучайный вывод.

Вместо этого попробуйте:

int main()
{
  printf("%d", 10101);
}

НТН

12 голосов
/ 07 октября 2009

Это классическое неопределенное поведение . Компилятор не проверяет, что вы предоставили достаточно аргументов для соответствия вашей строке форматирования. Есть компиляторы, которые делают это ( gcc - это один ), но ваш нет.

Код в printf() с удовольствием пройдет по заданной строке форматирования, и когда он доберется до «% d», он прочитает один int размерный аргумент (обычно: из стека), не зная там там нет аргументов для чтения.

Независимо от того, какое значение окажется в стеке, будет напечатано.

3 голосов
/ 07 октября 2009

Некоторые компиляторы, такие как gcc, будут обнаруживать такие типичные проблемы, если вы укажете достаточно высокий уровень предупреждения. Вот так (компилируя ваш код, с -Wall - все предупреждения):

gcc    -c -g -Wall -MMD -MP -MF build/Debug/Cygwin-Windows/newmain.o.d -o build/Debug/Cygwin-Windows/newmain.o newmain.c
newmain.c: In function `main':
newmain.c:16: warning: too few arguments for format

Это одна из 998 веских причин всегда компилировать с высоким уровнем предупреждения и серьезно относиться к предупреждающим сообщениям.

2 голосов
/ 07 октября 2009

Код показывает неопределенное поведение. В других системах это может вывести «Переполнение стека» (серьезно!). % d сообщает библиотеке CRT, что вы предоставите целое число, но вы этого не сделаете.

0 голосов
/ 07 октября 2009

Я предполагаю, что вы компилируете

main(){ printf("%d");}

Это выберет случайное значение из текущего стека. Попробуйте это:

main() {
   printf("%d", 0);
   printf("%d");
}

Теперь второй printf() всегда будет печатать 0, поскольку он получает тот же стек, что и первый вызов.

[EDIT] Это не работает на x86 Linux с GCC 4.1.2. Вот сгенерированный ассемблерный код (используйте gcc -S -o t.s t.c):

    movl    $0, %esi
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf
    movl    $.LC0, %edi
    movl    $0, %eax
    call    printf

Как видите, второй аргумент не помещается в стек, а передается через %esi (который является регистром). Этот же регистр, вероятно, изменен в printf(), поэтому он теряет свое значение. Чертовы оптимизации;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...