#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;
fromheader.h
— это предварительное определение с внешней привязкой. Вы можете включитьheader.h
из нескольких единиц перевода, и компоновщик свернет их в одну.
Ответ №3:
TOS=0
это не присвоение, это объявление с инициализатором (т. е. определение). int TOS;
это предварительное определение с внешней привязкой. Когда компоновщик связывает несколько единиц перевода вместе, он сворачивает соответствующий объект (= память для переменной). Как уже говорилось в другом месте, тип по умолчанию int
— это функция C89, отсутствующая в более поздних выпусках стандарта.
Комментарии:
1. Нет. Во-первых, в стандарте C нет такого понятия, как предварительное объявление, есть предварительные определения . И затем предварительные определения требуют, чтобы не было инициализатора: объявление идентификатора для объекта, который имеет область действия файла без инициализатора и без спецификатора класса хранения или со статическим спецификатором класса хранения, составляет предварительное определение.