Каков вывод следующего кода? - PullRequest
4 голосов
/ 01 октября 2010
int main()
{
  int x=5,y=10,z=15;
  printf("%d %d %d");
  return 0;
}

Выход: 15 10 5 // В Turbo C 4.5

    3 Garbage values in gcc compiler

Мой учитель сказал мне, когда мы определяем переменные, такие как int x = 5, y = 10, z = 15;по умолчанию они считаются автоматически вводимыми и сохраняются в стеке. Когда вы пытаетесь напечатать 3 целочисленных значения без использования их имен с помощью printf (), он напечатает эти 3 значения в формате LIFO, как это делает компилятор Turbo C.Но я думаю, что когда мы определяем 3 целочисленные переменные, они не могут храниться в непрерывных ячейках памяти. Поэтому, когда я пытаюсь напечатать 3 целочисленных значения без использования их имен, компилятор выводит любые три значения из верхней части стека.на выход придут 3 значения мусора как в gcc ..

Ответы [ 6 ]

10 голосов
/ 01 октября 2010

Этот код просто показывает, что Turbo C плохо оптимизирует код и помещает все в стек, тогда как gcc более агрессивен и сохраняет его в регистрах или отбрасывает все вместе потому что эти три переменные не имеют смысла.

В любом случае, вызов printf с шаблоном, который требует трех аргументов без предоставления этих аргументов, является ошибкой.

Обновление:

В качестве объяснения: я предполагаю, что printf () всегда будет принимать свой аргумент из стека, поскольку это функция со списком переменных аргументов. Или кто-нибудь знает какое-либо другое соглашение о вызовах для таких функций, как printf () ? Кроме того, я предполагаю, что нет необходимости помещать что-либо еще в стек, так как нет других переменных. Так что этот ошибочный вызов printf напечатает все, что находится на вершине стека в main () . Но могут быть и другие архитектуры и соглашения о вызовах, в которых мои предположения не выполняются.

4 голосов
/ 01 октября 2010

Это неопределенное поведение.

При использовании оптимизирующего компилятора эти 3 значения могут быть оптимизированы, поскольку они не используются.Будет печатать мусор.

3 голосов
/ 01 октября 2010

Поведение не определено, что означает, что компилятор может свободно обрабатывать ситуацию любым удобным для него способом. Что касается языкового стандарта, то и Turbo C, и gcc делают «правильные» вещи.

2 голосов
/ 01 октября 2010

Если для формата недостаточно аргументов, поведение не определено.

1 голос
/ 01 октября 2010

Ваш учитель не прав, но не полностью.

Переменные, объявленные в функции, по умолчанию auto, а не static.

int foo(void) {
    static int x;
    int y;
    auto int z;

    /* ...other code... */
}

Это означает, что в функциивыше y - auto, как и z, хотя ключевое слово auto не используется в его объявлении.Кстати, ключевое слово * 1010 почти никогда не используется.Многие программисты на C (и на производном языке C) даже не знают, что auto является ключевым словом, потому что оно используется так редко.

Наличие переменной auto обычно означает, что переменная хранится в программе.системный стек или в регистрах или какое-то их сочетание.Во время выполнения функции она может находиться в разных местах в разное время, и локальные переменные, которые находятся в регистрах, часто помещаются в стек при вызове другой функции.Некоторые локальные переменные могут даже быть оптимизированы, что означает, что в какой-то момент компилятор смог определить, что будущее значение конкретной переменной больше не требуется для удовлетворения входных потребностей будущего кода (или переменная не изменяется и ее значениепросто закодировано в инструкции).Это усложняет использование отладчиков для оптимизированного кода.

Когда вы берете адрес локальной переменной, компилятор затем пытается заблокировать его по определенному адресу (возможно, сохраняя его в стеке).

Когда большинство компиляторов проверят ваш код, они увидят, что имена этих локальных переменных не используются после их объявления, и могут решить просто не хранить свои значения где-либо.Даже если он сохраняет эти значения в стеке, он также может выдвинуть другие значения в стеке перед установкой вызова printf.Так же, как компилятору не нужно хранить переменные, которые вы назвали, он также может создавать свои собственные временные переменные.

0 голосов
/ 01 октября 2010

В MingW-GCC: 3 значения мусора.

В VC ++ 2010: 0, 0 и значение мусора.

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