Это
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 Если внутри единицы перевода появляется один и тот же идентификатор как с внутренней, так и с внешней связью, поведение не определено.