статические и внешние встроенные функции в C [дубликат]
На этот вопрос уже есть ответ здесь:
в чем разница между статической встроенной, внешней встроенной и обычной встроенной функцией?
1 ответ
Я пытаюсь подробно изучить разницу между статическими и внешними функциями.
Я знаю основное различие между статическими и внешними встроенными функциями.
Пожалуйста, исправьте мой понимание, если это неправильно:
- статические встроенные функции видны только той единице перевода, где она определена.
- внешние встроенные функции могут быть доступны в нескольких единицах перевода.
- лучше определять встроенные функции в заголовочных файлах
- нет разницы между статическими и статическими определениями встроенных функций.
Ниже приведен пример кода, в котором я застрял по поводу поведение.
Файл1.c
#include <stdio.h>
#include "file.h"
int main(void)
{
fun1();
return 0;
}
static inline void fun1(void)
{
int i;
for (i = 0; i < 10; i++) {
static int k = 20;
printf("Value : %d n", k++);
}
}
Файл 2.c
#include <stdio.h>
inline void fun1(void)
{
int i;
int k = 0;
for (i = 0; i < 10; i++) {
printf("Value : %d n", k++);
}
}
Файл.h
#ifndef FILE_H
#define FILE_H
extern inline void fun1(void);
#endif
Когда я компилирую приведенный выше код " GCC file1.c file2.c", fun1 был вызван из file2.c. это ясно, поскольку он fun1 объявлен как extern, он должен принимать функцию extern в file2.c( все встроенные функции по умолчанию являются extern?).
Но когда я изменяю статическую встроенную функцию на статическую функцию (static void fun1 (void)) в файле file1.c, fun1 был вызван из файла 1.В. В чем может быть причина? ?
Я также читаю как "если встроенная функция объявлена с внешней связью, но не определена в той же самой единице перевода, поведение не определено". Но я этого не понимал. Можно ли это объяснить на приведенном выше примере?
Есть ли разница между статическими и внешними функциями в C++ по сравнению с C ?
1 ответ:
Ваш код неверен, потому что вы не можете объявить функцию с
extern(что является значением по умолчанию), а затем предоставить определениеstatic. Тот факт, что он компилируется вообще, не указывает ни на что полезное.Из n1548 §6.2.2:
Если в пределах единицы перевода появляется один и тот же идентификатор с внутренней и внешней связью, поведение не определено.
Итак, вы получаете что-то вроде этого в
file1.c:// Has external linkage (which is the default!) extern inline void fun1(void); // This would also have external linkage. inline void fun1(void); // This has static linkage. static inline void fun1(void) { ... }(Примечание: "внешняя связь" это значение по умолчанию, но
extern inlineна самом деле означает что-то особенное, оно отличается отinline.)БАМ! Неопределенное поведение. Компилятор может даже не выдать вам сообщение об ошибке, хотя некоторые компиляторы, похоже, выдают сообщения об ошибках для этого.
error: static declaration of 'func' follows non-static declarationЭта ошибка на самом деле не имеет ничего общего с тем, что функция
inline. Это ошибка С или безinline., что по поводу этих вопросов?
Это справедливо для всех функцийСтатические встроенные функции видны только для единица перевода, где она определена.
. Они имеют "внутреннюю связь", поэтому вы можете иметь
static void func(void);в одном файле и совершенно другойstatic int func(char *p);в другом файле.inlineздесь не имеет значения.Внешние встроенные функции могут быть доступны в нескольких единицах перевода.
Да, именно поэтому вы не должны помещать их в заголовочные файлы. Если вы поместите их в заголовочные файлы, вы получите несколько различных определения одной и той же функции, которые могут быть доступны из разных единиц перевода. Это ошибка. Вместо этого поместите
extern inlineв исходные файлы, но это должно быть только объявление, а не определение.Лучше определять встроенные функции в заголовочных файлах
Нет никакого реального смысла определять встроенную функцию где-либо еще. Если ваша функция используется только в одном файле, просто отметьте ее
static, и компилятор решит, как вызвать функцию. функция.Нет разницы между статическими и статическими определениями встроенных функций.
Да, нет никакой разницы.
Ну, технически, нет, есть разница, потому что компилятору разрешено обрабатывать функцииstatic inlineиначе, чем просто функцииstatic. Однако современные компиляторы, как правило, решают встроить функции, используя свой собственный набор правил, и то, является ли функцияinline, не очень влияет на этот процесс.Ну, практически есть еще одно отличие. Определение функции
Итак, как вы делаете это правильно?static inlineне будет генерировать предупреждение в GCC, если оно не используется, но функцияstaticбудет. Это делается для того, чтобы вы могли поместить функциюstatic inlineв заголовочный файл. Это альтернатива помещениюinlineв заголовочный файл, который требует наличияextern inlineдля этой функции где-то в вашей программе. Однако, если компилятор решит, что он предпочел бы не инлайнировать вашу функциюstatic inline, либо потому, что он думает, что инлайн хуже, либо потому, что инлайнинг невозможен, тогда ему придется сделать отдельную копию этой функции в каждом файле, в котором он используется.Никогда не объявляйте функцию
static, если она имеет предыдущее, нестатическое объявление. Это ошибка, даже если она компилируется.Не объявляйте функцию
inline externв заголовочном файле. Это создает "внешнее определение" для функции, и вы можете иметь только одно из них во всей своей программе.Не объявляйте
inlineфункции в заголовочных файлах без их определения. В этом нет никакого смысла.Вот как вы хотели бы это сделать:
В
mylib.h:// Provide "inline definition" of the function. inline int times_two(int x) { return x * 2; }В
mylib.c:#include "mylib.h" // Provide "external definition" of the function. extern inline int times_two(int x);Это стандартный способ делать вещи, начиная с C99. Компилятор должен быть свободен использовать внутреннее определение или внешнее определение, какое он считает лучшим. Если у вас нет внешнего определения или у вас есть более одного, вы можете получить ошибку связывания, так же, как с обычным функции.
C++ имеет свои собственные совершенно разные правила для встроенных функций.
Comments