#c #gcc
#c #gcc
Вопрос:
ниже приведен код:
//test.h
...
extern int globalVariable;
...
//test.c
#include "test.h"
...
int globalVariable = 2020;
...
//main.c
#include <stdio.h>
#include "test.h"
int main()
{
printf("Value is %d", globalVariable);
}
допустим, в сценарии объявлены сотни переменных, test.h
и globalVariable
это всего лишь одна из них.
поскольку существует множество переменных, я легко допускаю ошибку опечатки в test.c
как:
#include "test.h"
int globalVariables = 2020; //extra 's' in the name which contradicts the declaration of its counterpart in test.h
если я скомпилирую (только скомпилирую, не связывая их) test.c
, test.h
и main.c
, он скомпилируется и не покажет ошибки. неразрешенная ошибка возникнет только тогда, когда компоновщик задействован на этапе компоновки.
Но в большом приложении я мог бы просто написать некоторые модули без необходимости связывать все существующие с исполняемым файлом, поэтому было бы лучше, если бы компилятор выдавал ошибку на этапе компиляции, чтобы указать ошибку, чтобы я мог исправить их как можно скорее, так как я могу позволить компилятору принудительно реализовать определение исходного файла для файла заголовка?
Ответ №1:
Вы также могли бы использовать препроцессор
test.h:
#ifndef TEST_C_IMPLEMENTATION
#define DEFINE_AND_INIT_VARIABLE(type, name, value)
extern type name;
#else
#define DEFINE_AND_INIT_VARIABLE(type, name, value)
type name = value;
#endif
DEFINE_AND_INIT_VARIABLE(int, globalVariable, 2020);
test.c:
#define TEST_C_IMPLEMENTATION
#include "test.h"
Этот метод можно использовать еще дальше — существуют небольшие служебные библиотеки, которые поставляются в виде единого включаемого файла; вам просто нужно установить макрос в одном из блоков перевода, чтобы принудительно скомпилировать реализацию в нем.
Ответ №2:
В объявлении extern int globalVariable;
говорится, что переменная существует где-то, но не обязательно в текущей единице перевода. Таким образом, любой исходный файл, который включает заголовок, содержащий это объявление, будет знать, что переменная существует, не требуя полного определения.
Затем, когда вы перейдете к этапу компоновки, вы получите сообщение об ошибке, касающееся glovalVariable
того, что оно не определено. Поскольку переменные объявлены в test.h, по соглашению определение должно быть в test.c. После проверки этого файла вы бы обнаружили, что такой переменной не существует, и могли бы затем либо добавить ее, либо найти опечатку и исправить ее.
Комментарии:
1. @dbusg таким образом, я не буду предупрежден об опечатке, пока не создам компоновку файлов?
2. @dbush прав. Ваш вопрос касается реализации соглашения о кодировании. Если вы хотите, вы можете реализовать эту проверку в виде сценария и выполнить его как часть вашего makefile (или процесса сборки). Например: Скрипт, который извлекает список объявлений extern из файлов .h и определения extern из файлов .c и находит записи в списке .h, которых нет в списке .c. Имейте в виду, что вам, возможно, придется реализовать мини-анализатор C для обработки объявлений extern и определений переменных. Если вы действительно собираетесь пойти по этому пути, попробуйте ANTLR, который может сгенерировать анализатор на основе грамматики C.