Распределение памяти для встроенной и нормальной функции - PullRequest
1 голос
/ 07 апреля 2020

Какая область памяти используется функцией и параметром функции? Кроме того, в какой области выделена память для встроенной функции?
Если я вызываю встроенную функцию внутри нормальной функции несколько раз, будет ли память выделяться для встроенной функции несколько раз?

Ниже приведен пример программы

inline int add (int a, int b)
{
      return A+B;
}

int calculation(int c , int d)
{
    int ret;
    for (int i=0; i < 3; i++) {
           ret = add(c, d);
           c++;
           d++;
     }
     return ret;
}

Где будет выделена память для a & b и c & d?

Ответы [ 2 ]

2 голосов
/ 07 апреля 2020

Области памяти не стандартизированы, хотя де-факто существуют стандарты, такие как ELF , что является общим форматом как для Unix -подобных систем, так и для встраиваемых систем.

Предполагается, что ELF -подобная система, область, где хранится исполняемый код, называется .text. Не имеет значения, является ли функция встроенной или нет, ее машинный код окажется в этом сегменте.

Нормальная функция сохраняет свои параметры либо в регистрах, либо в стеке. Это системная спецификация c и зависит от "ABI" (двоичный интерфейс приложения). Когда такая функция становится встроенной, может не потребоваться копировать переменные из вызывающей стороны, и в этом случае они остаются в любом регистре или области, в которой они уже были размещены.


Что касается того, что произойдет в приведенном вами примере кода c функция не содержит побочных эффектов, а результаты не сохраняются, поэтому на самом деле актуален только последний круг в течение для l oop. L oop был бы выполнен 4 раза, поэтому различные операции ++ сводятся к 2 + 2 = 4.

Сгенерированный машинный код на оптимизирующем компиляторе x86 сводится к

lea     eax, [rdi+4+rsi]
ret

Что в эквивалентном C коде в значительной степени означает, что ваш код был заменен следующим:

int calculation(int c , int d)
{
  return c + d + 4;
}

Это потому, что сам алгоритм бессмысленен, в большей степени, чем встраивание. Компилятор вполне может встроить это без клавиатуры inline и сделает это с включенной оптимизацией.

0 голосов
/ 07 апреля 2020

Подстановка указывается компилятором c. Однако вы можете воспринимать это как серию преобразований в код.

Начиная с исходного кода:

ret = add(c, d);

Сначала экспортируются аргументы функции:

int a = c;
int b = d;
ret = add(a, b)

Затем тело функции встраивается:

int a = c;
int b = d;
ret = a + b

Тогда будут выполняться все другие виды оптимизации, однако в худшем случае (только приведенный выше код без какой-либо оптимизации) переменные a и b будут в стеке после переменной ret.

Суть в том, что не будет много выделений, только одно. int a =... и int b = ... может показаться, что они размещаются в каждом l oop, но в действительности они выделяются при вызове функции, как если бы они были сразу после оператора int ret.

...