В чем разница между статическим встроенным void и void?
Я работаю на языке C и, изменяя код, ранее написанный кем-то другим. Я борюсь с некоторыми вещами и пытаюсь понять как можно больше о том, что происходит. Итак, как говорится в моем вопросе, в чем разница между static inline void
и void
при создании функции? Заранее приношу извинения за длинный пост, но я хотел, чтобы вы знали, что я провел некоторые исследования, но не понимаю, что я нашел.
нашел объяснение static
что меня смущает:
статический спецификатор означает, что на функцию нельзя ссылаться из других файлов; то есть, имя не экспортировали линкер.
читая это, я предполагаю, что ссылка на функцию отличается от вызова функции? Я предполагаю, что потому что эта функция вызывается из другой .файл c. Если это так, то что такое ссылка на функцию?
5 ответов
static
означает, что на него нельзя ссылаться из другого блока компиляции (исходного файла). "Ссылка" означает вызываемый или иным образом упоминаемый по имени, например назначенный указателю функции.
inline
- это подсказка компилятору, что код функции должен быть сгенерирован inline в том месте, где он вызывается, а не сгенерирован как отдельная функция для ветвления. Обычно это делается по соображениям производительности. Чтобы разобраться с цитатой Microsoft:
в компилятор не вставляет функцию, если ее адрес взят или если он слишком большие встроенный.
встроенная функция не имеет адреса, так как она не существует как отдельная сущность. Его код просто легко переплетается с кодом, из которого он вызван. Таким образом, если вы берете адрес функции (например, для назначения указателю), компилятор должен генерировать ее как реальную функцию и не может встроить ее.
void
означает, что функция не возвращает значение.
посмотрев на ваш образец кода, я бы предположил, что существует отдельное определение CGauss()
где-то, откуда вызывается file1.c, тогда как file2.c звонит собственной версии. Или это, или file1.c и #include
ing file2.c. Что было бы отвратительно.
static
означает только то, что у вас есть более одного исходного файла. Он указывает, что static
функция или переменная не могут быть доступны из функций в другом файле.
inline
- это оптимизация компилятора, которая ускоряет ваш код в определенных случаях. Всякий раз, когда вы вызываете функцию, с ней связаны некоторые накладные расходы. Таким образом, компилятор может избавиться от функции все вместе, скопировав+вставив (почти) встроенный код.
вот пример встраивания:
int dotproduct(int x1, int y1, int x2, int y2) {
return multiply(x1,x2)+multiply(y1,y2);
}
inline int multiply(int a, int b) {
return a*b;
}
компилятор превратит это в:
int dotproduct(int x1, int y1, int x2, int y2) {
return x1*x2+y1*y2;
}
если вы хотите быть причудливым, вы также можете встроить функцию dotproduct;)
отметим, что inline
ключевое слово-это просто подталкивание компилятора к встроенным определенным функциям. Он может сделать это в зависимости от собственных суждений она.
static ключевое слово
определение функции C static означает (как врачи говорят), что эта функция может быть доступна только из исходного файла, в котором она определена. Термин "ссылка" в этом смысле означает либо вызов этой функции, либо, например, указатель на нее.
подстановкой
обычно, когда вы пишете функцию в C, компилятор генерирует машинный код для этого функция:
foo:
/* some machine code */
ret
каждый раз, когда вы вызываете эту функцию, компилятор вставляет обучения, такие как
call <foo>
в машинный код вызывающего абонента, что означает не что иное, как " перейти к foo, выполнить то, что вы найдете там, и когда вы столкнетесь с инструкцией ret, вернитесь в это место."
напротив, для встроенных функций компилятор не генерирует отдельную функцию foo(), а вместо этого вставляет машинный код для функции foo в каждый вызов сайт. При выполнении этого кода, это имеет тот же эффект.
Так почему мы делаем это? Встроенный код имеет преимущество сохранения двух прыжков (вызов и соответствующий ret), что делает ваш код выполняется немного быстрее. Как недостаток, ваш код становится больше, потому что вы вставляете машинный код на каждый сайт вызова вместо того, чтобы иметь только одну копию вызываемой функции. Вот почему вы обычно только встроенные небольшие функции.
кроме того, вы не можете принимать указатели на функции встроенные функции, и отладка становится сложнее, потому что вы не можете установить точку останова на встроенной функции легко.
таким образом, вставка остается для компилятора в качестве опции оптимизации и с помощью ключевого слова, такого как C++'S inline, your встроенная директива или атрибут __GCC((inline)), вы только даете компилятору подсказку, что встраивание может стоить попробовать здесь.
static просто означает, что по существу функция для всех намерений и целей "невидима" вне исходного файла, в котором она определена.
inline askes компилятор, чтобы по существу заменить код вызова функции непосредственно в источник в каждом месте, функция вызывается во время компиляции (например, замена вызова функции кодом функции) - однако это не гарантируется, это просто предлагает его вашему компилятору.
Это более технический, чем это, и вы, вероятно, получите гораздо лучший ответ, но на простом языке это то, что означают термины.
Я хотел бы добавить ко всему вышесказанному, прежде чем читать выше, важно понять, как работает программирование на Си. Если вы просто напишите открытый код, например
Setup(){
int MainVar
}
MyRoutine(){
int myVar1;
int myVar2;
bool myVar3;
// Do stuff with myVars
MainVar = myVar1 - myVar2;
myVar3 = true;
}
тогда любой может открыть MyRoutine.myVar1 непосредственно из второй программы. Они могут изменить значение myVar2, (1. если он не защищен, 2. если они знают, что он там, 3. если они знают, что он делает), прежде чем он будет использоваться в MyRoutine / / делать вещи, тем самым изменяя то, что оригинальный программист предназначенный.
представьте, что вы пишете банковскую программу и оставили код уязвимым, чтобы кто-то мог изменить стоимость депозита, не изменяя вывод средств из другого банка в вашей рутине. Кто-то другой мог прийти и написать отдельную программу, чтобы изменить это значение на 2 или 10 и создать деньги там, где их не было. Но если вы предшествуете коду, подпрограмме, методу или переменным со статическими, эти элементы не могут быть доступны, просмотрены и, самое главное, изменены другим программа.
вы можете использовать статику в любой момент, делая целые процедуры закрытыми или только отдельные переменные закрытыми. Таким образом, позволяя другим вносить изменения в определенные аспекты вашего кода, но сохраняя те аспекты, которые необходимо защитить.
включение статики в MyRoutine помешает кому-то выполнить MyRoutine из другой программы. Поскольку MyVars объявлены в MyRoutine, они не будут доступны из другой программы. Но если бы была переменная названный MainVar, объявленный в другом месте программы, он будет доступен.
Setup(){
int MainVar // This can be accessed from outside this code
}
static MyRoutine(){ // Because of static these vars are not
int myVar1;
int myVar2;
bool myVar3;
// Do stuff with myVars
MainVar = myVar1 - myVar2;
myVar3 = true;
}
и здесь защищены только переменные со статикой. myVar3 можно прочитать из другого места, сообщая другую процедуру, которую завершил обмен.
Setup(){
int MainVar // This can be accessed from outside this code
}
MyRoutine(){
static int myVar1; // This can NOT be accessed from outside this code
static int myVar2; // This can NOT be accessed from outside this code
bool myVar3; // This can be accessed from outside this code
// Do stuff with myVars
MainVar = myVar1 - myVar2;
myVar3 = true;
}