Странное предупреждение GCC о классе и типе хранилища

#c #gcc #gcc-warning

#c #gcc #gcc-предупреждение

Вопрос:

У меня есть файл заголовка, который выглядит как

header.h

 int TOS;
  

Этот файл включается только одним файлом кода

code.c

 #include "header.h"
TOS=0;
  

При компиляции кода.c GCC выдает предупреждение

code.c: 3:1: предупреждение: определение данных не имеет типа или класса хранилища [включено по умолчанию] code.c: 3:1: предупреждение: тип по умолчанию равен ‘int’ в объявлении ‘TOS’ [включен по умолчанию]

Я не понимаю причину этого предупреждения. Разве это не эквивалентно объявлению и определению TOS в code.c? т.е.

code.c

 int TOS;
TOS=0;
  

Комментарии:

1. У вас есть main() право?

2. Да, main() есть. Просто опустил его для краткости.

3.И TOS=0; это внутри main() ?

Ответ №1:

Это потому, что вы определяете TOS в глобальной области видимости, которая требует от вас определения типа TOS (это объявление), если тип не был задан, по умолчанию это int .

Это приведет к conflicting type error ,

 char x;
x = 0;
  

Комментарии:

1. Но почему нельзя объявить a глобальным и определить его позже??

2. @Я думаю, это потому, что компилятор разрешает только объявление переменных и инициализацию в глобальной области видимости, но не присваивание.

Ответ №2:

Правильным способом пересылки переменной в заголовочном файле было бы

 extern int TOS;
  

без extern это могло бы в противном случае привести к тому, что TOS будет выделено в нескольких единицах компиляции (файлах .o).

Затем вы бы дали определение в одном файле .c как

 int TOS;
  

Затем это зарезервировало бы для него место , и поскольку это переменная в глобальной области видимости , она также инициализировала бы его на 0 . Если вы хотите сделать эту инициализацию явной или если вы хотите, чтобы она имела другое значение, отличное от 0 , правильный синтаксис для инициализации (а не присваивания) является

 int TOS = 54;
  

Современный C не допускает синтаксиса, который вы, похоже, откуда-то унаследовали, а именно определения глобальной переменной с неявным типом int .

Комментарии:

1. Хотя TOS были бы выделены в нескольких единицах перевода, в C (но не в C ) компоновщик должен свернуть их в одну.

2. @ninjalj, нет, я так не думаю. Я думаю, это было бы только в том случае, если инициализации нет. Если в выражении используется идентификатор, объявленный с внешней связью .. где-то во всей программе должно быть ровно одно внешнее определение идентификатора; в противном случае должно быть не более одного.

3. int TOS; from header.h — это предварительное определение с внешней привязкой. Вы можете включить header.h из нескольких единиц перевода, и компоновщик свернет их в одну.

Ответ №3:

TOS=0 это не присвоение, это объявление с инициализатором (т. е. определение). int TOS; это предварительное определение с внешней привязкой. Когда компоновщик связывает несколько единиц перевода вместе, он сворачивает соответствующий объект (= память для переменной). Как уже говорилось в другом месте, тип по умолчанию int — это функция C89, отсутствующая в более поздних выпусках стандарта.

Комментарии:

1. Нет. Во-первых, в стандарте C нет такого понятия, как предварительное объявление, есть предварительные определения . И затем предварительные определения требуют, чтобы не было инициализатора: объявление идентификатора для объекта, который имеет область действия файла без инициализатора и без спецификатора класса хранения или со статическим спецификатором класса хранения, составляет предварительное определение.