Функция my_func предоставляется компоновщику или нет для этого примера? - PullRequest
2 голосов
/ 31 октября 2019

Я хочу дополнительно понять, доступна ли функция my_func () компоновщику для следующего сильно сокращенного примера. Основы, которые имеют приоритет, предварительное объявление или объявление?

Я предполагаю предварительное объявление, но почему? Может кто-нибудь, пожалуйста, объясните, ref. к K & R все в порядке

static int my_func(void);

<Use my_func here>

int my_func(void)
{
  return 1;
}

что если пример будет изменен на

static int my_func(void);
int my_func(void);

<Use my_func here>

int my_func(void)
{
  return 1;
}

1 Ответ

1 голос
/ 31 октября 2019

Это

static int my_func(void);

уже является объявлением функции с внутренней связью.

Таким образом, следующее объявление

int my_func(void);

является избыточным.

Эти декларации

static int my_func(void);
int my_func(void);

эквивалентны

static int my_func(void);
extern int my_func(void);

Из стандарта C (6.2.2 Связи идентификаторов)

5 Еслиобъявление идентификатора для функции не имеет спецификатора класса хранения, его связь определяется точно так, как если бы он был объявлен с помощью спецификатора класса хранения extern.

И

4 Для идентификатора, объявленного с помощью спецификатора класса хранения extern в области видимости, в которой видно предыдущее объявление этого идентификатора, 31) если в предыдущем объявлении указана внутренняя или внешняя связь, то связьидентификатор в более позднем объявлении совпадает со связью, указанной в предыдущем объявлении. Если предыдущее объявление не видно или если в предыдущем объявлении не указана связь, то идентификаторifier имеет внешнюю связь.

Таким образом, в этом фрагменте кода

static int my_func(void);
int my_func(void);

<Use my_func here>

int my_func(void)
{
  return 1;
}

у вас есть три объявления одной и той же функции с internal linkage и объявлением

int my_func(void);

, как было сказано ранее, является избыточным.

Это означает, что функция не видна в других единицах перевода. Или, если объявление функции со статическим спецификатором класса хранения помещено в заголовок, тогда каждая единица перевода, которая включает в себя заголовок, имеет свою собственную функцию с тем же именем.

Если вы будете писать вместо этого, например,

int my_func(void);
static int my_func(void);

тогда поведение не определено, поскольку одно и то же имя определяется как имеющее внешние и внутренние связи.

Из стандарта C (6.2.2 Связи идентификаторов)

7 Если внутри единицы перевода появляется один и тот же идентификатор как с внутренней, так и с внешней связью, поведение не определено.

...