нестатическое объявление после статического объявления - PullRequest
4 голосов
/ 30 августа 2011

Рассмотрим эти примеры:

static int a;
extern int a; //OK -- what linkage does the a have now?

static int a;
int a; //ERROR

extern int a;
static int a; //ERROR

int a;
static int a; //ERROR

extern int a;
int a; //OK as expected

int a;
extern int a; //OK as expected

Почему в первом примере все было в порядке, а во втором - нет?

Что касается переменных области файла (global-scope), они имеют внешнюю связь и статическую длительность, когда ключевое слово не указано.

Спасибо

AFAIK, время связывания и хранения для функций немного отличается.

EDIT: Я попытался скомпилировать с помощью gcc 4.5.2 -Wall -pedantic --std = c99

Подробнее: http://c -faq.com / decl / static.jd.html Вы можете видеть, что 1-й пример тоже работает, а 2-й нет. Однако я не понимаю, чем они отличаются.

Ответы [ 2 ]

3 голосов
/ 30 августа 2011

Ответ на ваш первый вопрос можно найти в §6.2.2 стандарта C:

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

Таким образом, связь a является внутренней.

По вашему второму вопросу второе предложение следующего за ним абзаца уместно:

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

Поскольку a является объектом, а не функцией, объявление int a; без спецификатора класса хранения дает a внешнюю связь. Затем в этом же разделе говорится:

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

Поскольку во втором примере a отображается как с внутренней, так и с внешней связью, этот параграф запускается. Одним (особенно полезным) проявлением неопределенного поведения является ошибка, которую генерирует ваш компилятор.

Все ваши примеры можно понять по следующим правилам:

  1. int a; всегда объявляет a с внешней связью;
  2. static int a; всегда объявляет a с внутренней связью;
  3. extern int a; объявляет a с какой-либо связью, которая у него уже была, или с внешней связью, если у нее ее нет;
  4. Два объявления a в одной и той же области с разными связями дают неопределенное поведение.
0 голосов
/ 27 июня 2019

Я получаю ту же ошибку, когда забываю "{" вместо ";"в конце объявления.

Пример:

extern void *HASHMP_get(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key);
extern void *HASHMP_remove(struct HASHMP_wf_s *hmwf_ptr, Uint8 *key) {
extern Uint16 HASHMP_clear(struct HASHMP_wf_s *hmwf_ptr);
...