статические и внешние встроенные функции в C [дубликат]



На этот вопрос уже есть ответ здесь:




Я пытаюсь подробно изучить разницу между статическими и внешними функциями.

Я знаю основное различие между статическими и внешними встроенными функциями.



Пожалуйста, исправьте мой понимание, если это неправильно:




  • статические встроенные функции видны только той единице перевода, где она определена.

  • внешние встроенные функции могут быть доступны в нескольких единицах перевода.

  • лучше определять встроенные функции в заголовочных файлах

  • нет разницы между статическими и статическими определениями встроенных функций.


Ниже приведен пример кода, в котором я застрял по поводу поведение.



Файл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 ?

560   1  
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

    Ничего не найдено.