Создание переменной в стеке в C - PullRequest
0 голосов
/ 08 ноября 2018

Мне интересно, создана ли переменная в стеке или нет. Рассмотрим следующие три функции f, g и h с переменной b:

void f(int a) {
    int b;
    if (a == 0) {
        return;
    }
    // do sth with b;
    return;
}

void g(int a) {
    if (a == 0) {
        return;
    }
    int b;
    // do sth with b;
    return;
}

void h(int a) {
    if (a == 0) {
        return;
    } else {
        int b;
        // do sth with b;
        return;
    }
}
  1. В каких случаях будет создаваться b в стеке?
  2. Как уровень оптимизации компилятора влияет на это поведение?
  3. Есть ли один вариант, который предпочтительнее?

Ответы [ 3 ]

0 голосов
/ 08 ноября 2018

Каждая функция имеет свой собственный фрейм (место, где будут храниться все локальные переменные, параметры и т. Д.).Все локальные переменные являются автоматическими переменными, потому что они будут уничтожаться после оператора return.Все переменные, которые были созданы без (malloc, calloc, realloc и т. Д.), Будут храниться в стеке.Итак, да, все переменные в вашем коде будут храниться в стеке.

0 голосов
/ 08 ноября 2018

В каких случаях будет создаваться b в стеке?
Как уровень оптимизации компилятора влияет на это поведение?

Невозможно сказать без конкретной системы. Это зависит от соглашения о вызовах и от того, как компилятор оптимизирует код. Он может быть размещен в стеке или внутри регистра.

При этом ваши 3 дела в основном касаются стиля кодирования. Если b необходим и размещен в стеке, эта память, вероятно, будет выделена раньше, независимо от того, где находится переменная. Или аналогичным образом, если компилятор может оптимизировать использование памяти на основе того, используется ли переменная или нет, компилятор будет выделять память непосредственно перед использованием переменной, независимо от того, где находится объявление переменной в исходном коде C.

Есть ли один вариант, который предпочтительнее?

Как правило, держите объявление переменной близко к месту его использования. Если вы можете сузить сферу, это всегда хорошо. Но это ради сокращения области видимости, предотвращения коллизий пространства имен, частной инкапсуляции и т. Д. Не ради производительности.

0 голосов
/ 08 ноября 2018

В каких случаях будет создаваться b в стеке?

Обычно все три, поскольку b является автоматической переменной. В некоторых случаях компилятор может хранить b в регистре процессора , но вы не можете заставить это произойти, это выбор компилятора.

Как уровень оптимизации компилятора влияет на это поведение?

Зависит от компилятора.

Поскольку вы предполагаете, что вы что-то делаете (полезно) с b, это, вероятно, не будет оптимизировано. Если это произойдет, что зависит от компилятора и от того, что именно вы делаете с b, тогда b вообще не будет создан в стеке.

Есть ли один вариант, который предпочтительнее?

Создайте переменную b как можно ближе к ее использованию, в верхней части блока, где это необходимо.

Я бы выбрал g(), так как это самая лаконичная функция (для достижения той же цели используется минимальное количество символов в отличие от других). Более того, он создает b непосредственно перед его использованием.

PS: Конечно, g() может использовать только один return, но вы поймете идею.

...