Встроенные определения - PullRequest
6 голосов
/ 10 декабря 2011

pg474, K.N.King

"Общее правило в C99 состоит в том, что если все объявления верхнего уровня Функция в конкретном файле включает в себя встроенный, но не внешний, то определение функции в этом файле встроено. "

  • Что такое: "объявление функции верхнего уровня" ??

"Если функция используется где-либо в программе (включая файл который содержит свою встроенную декларацию), а затем внешнюю декларацию функция должна быть предоставлена ​​каким-то другим файлом. Когда функция вызвана, компилятор может выбрать для выполнения обычного вызова (используя внешнее определение функции) или выполнить встроенное расширение (используя встроенное определение функции). Там нет никакого способа, чтобы сказать, какие выбор, который сделает компилятор, поэтому очень важно, чтобы два определения быть последовательным. "

  • Что он здесь говорит ??

"Переменные со статической продолжительностью хранения представляют собой особую проблему для встроенные функции с внешней связью "

Но я думал, что вы не можете вызвать функцию с внешней связью! Компилятор выдаст ошибку:

pg 473

", поэтому попытка вызвать среднее из другой файл будет считаться ошибкой "

"Следовательно, C99 накладывает следующие ограничения на встроенный функция с внешней связью (но не с внутренней связью): Функция не может определять модифицируемую статическую переменную. Функция не может содержать ссылки на переменные с внутренним связь ".

Почему ?? Если функция встроенная и внешняя , то даже если она объявляет static int i; так как функция не может быть связана с вами, вы не можете вызвать ее, но не будет создана статическая переменная вне встроенных функций stack-frame - так что вы должны иметь возможность ссылаться на него? Делать встроенные функции есть кадр стека? Что здесь происходит?

1 Ответ

12 голосов
/ 10 декабря 2011

Я знаю, что написал много, но я попытался объяснить концепции хранения и связи вместе с моими пояснениями к вашему тексту. Надеюсь, это поможет!

"Общее правило в C99 состоит в том, что если все объявления верхнего уровня Функция в конкретном файле включает в себя встроенный, но не внешний, то определение функции в этом файле встроено. "

Что такое: "объявление функции верхнего уровня" ??

Объявление функции используется в форме, аналогичной объявлению переменной. Это единственный оператор, который объявляет имя, тип возвращаемого значения и типы параметров функции. Функция определение является действительным кодом функции.

Пример объявления:

int foo( int bar );

Пример определения:

int foo( int bar ){
    return -bar;
}
Объявление функции

A верхнего уровня - это просто объявление, которое находится в области действия file (т.е. вне какого-либо блока). Обычно это все объявления функций, хотя можно объявлять и определять функции внутри других функций.

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

Ха ??? Что он здесь говорит ??

Прежде всего, что такое связь? Связывание переменной или функции определяет, как компилятор будет обрабатывать несколько экземпляров этого объекта. Идентификаторы, которые не связаны, всегда являются «индивидуумами». То есть множественные объявления идентификатора в программе всегда обрабатываются как отдельные / отдельные объекты. Параметры функции и локальные переменные не имеют связи. Все ссылки на идентификатор с внешней связью относятся к одной и той же сущности. Это ключевое слово C 'extern'. По умолчанию глобальные идентификаторы имеют внешнюю связь. Это означает, что, например, если у вас есть глобальная переменная "int x;" в двух исходных файлах программы они будут связаны друг с другом и будут рассматриваться как одна и та же переменная. Внутренняя связь означает, что все объявления идентификатора в одном исходном файле ссылаются на одну сущность, но объявления одного и того же идентификатора в других исходных файлах ссылаются на разные сущности. Это способ C сделать вещи «частными» для файла. Это ключевое слово C «static» в области видимости файла.

Теперь вернемся к абзацу. Функция не может быть определена более одного раза. Поэтому исходные файлы, которые хотят использовать функции из других исходных файлов, должны включать внешнее объявление (которое является информацией, необходимой для вызова функции). Этот параграф объясняет, что происходит, когда файл имеет внешнюю декларацию для встроенной функции. Компилятор должен выбрать, должен ли он извлекать встроенное определение и вставлять его туда, где вызывается функция, или же он должен сохранять внешнюю связь, заставляя выполнение переходить к тексту кода, как обычно; и нет никакого способа предсказать, какой выбор сделает компилятор.

"Переменные со статической продолжительностью хранения представляют собой особую проблему для встроенные функции с внешней связью "

Но я думал, что вы не можете вызвать функцию с внешней связью! компилятор выдаст ошибку: pg 473 ", поэтому попытка вызвать среднее из другого файла будет считаться ошибка "

Если вы не можете вызвать функцию, которая определена в другом исходном файле (то есть внешне связанной функции), C будет действительно очень слабым и скучным языком!

"Следовательно, C99 накладывает следующие ограничения на встроенный функция с внешней связью (но не с внутренней связью): Функция не может определять модифицируемую статическую переменную. Функция не может содержать ссылки на переменные с внутренней связью. "

Почему ?? Если функция встроенная и внешняя, то даже если она объявляет статический int i; так как функция не может быть связана с вами, вы не можете вызвать это, но не будет создана статическая переменная вне встроенного функции стека-фрейма - так что вы должны иметь возможность ссылаться на него? Делать встраиваемые функции имеют стековый фрейм? Что здесь происходит ??

Статически хранимая переменная - это переменная, не являющаяся частью стека выполнения. Его пространство выделяется один раз, прежде чем программа начинает работать, и существует на протяжении всего выполнения. Они сохраняют свое первоначальное значение, пока не будет назначено другое значение. Глобальные переменные (область видимости файла) статически хранятся по умолчанию. Это отличается от автоматически сохраняемых переменных, которые размещаются в стеке непосредственно перед тем, как выполнение программы входит в блок, в котором они объявлены, и которые отбрасываются, когда выполнение покидает этот блок. Локальные переменные (область блока) по умолчанию являются автоматическими.

Возвращаясь к вопросу: в чем проблема со статически хранимой переменной внутри встроенной функции? Статически хранимая переменная внутри функции живет в предположении, что существует только одно определение этой функции и, следовательно, только одно определение этой статической переменной. Но встраивание, по определению, является повторением определения функции, поэтому вам не нужно прыгать по тексту во время вызова функции. Если бы в функции существовала статическая переменная, вам пришлось бы перейти к ее хранилищу, что исключило бы необходимость встраивания, то есть иметь копию всего «прямо там». Решение: требуется, чтобы переменная не была модифицируемой, чтобы компилятор мог встроить постоянное значение.

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

...