Просто игнорируй это
Если у вас есть охранники, это ложное предупреждение, которое можно (следует) игнорировать. Мы используем защитные ключи, потому что разрешить многократное включение файла - это хорошая практика, позволяющая создавать более гибкий код, предотвращать человеческие ошибки и избегать значения порядка в ваших операторах #include
. Если вы хотите узнать, почему это так, читайте дальше.
Несколько включений не проблема, потому что у вас есть охранники включения.
Поскольку все эти файлы .h довольно тесно связаны, я предполагаю, что вы включаете все три файла в один и тот же файл, возможно, main.c
:
#include "checksum.h"
#include "cryptography.h"
#include "crc8.h"
main () { /* Do Stuff */ }
Это будет расширено (за исключением комментариев, конечно) до:
// CHECKSUM_H is not defined, so the preprocessor inserts:
#include <GenericTypeDefs.h>
BOOL isCheckSumCorrect(const UINT8 *dataPointer, UINT8 len, UINT8 checkSumByte);
// CRYPTOGRAPHY_H is not defined, so the preprocessor inserts:
#include <GenericTypeDefs.h>
UINT8 encrypt(UINT8 c);
UINT8 decrypt(UINT8 c);
// CRC_H is not defined, so the preprocessor inserts:
#include <GenericTypeDefs.h>
UINT8 generateCRC(const UINT8 *ptr, UINT8 Len);
BOOL isCRCValid(const UINT8 *ptr, UINT8 Len, UINT8 CRCChar);
main () { /* Do Stuff */ }
Так что да, #include <GenericTypeDefs.h>
действительно появляется несколько раз в какой-то момент на этапе препроцессора. Якобы файл выглядит примерно так:
#ifndef GENERIC_TYPE_DEFS_H
#define GENERIC_TYPE_DEFS_H
#define UINT8 unsigned char
#ifdef __cplusplus
extern "C" {
#endif
так, после дополнительной предварительной обработки наш ранее расширенный бит (без комментариев) становится:
// GENERIC_TYPE_DEFS_H is not defined, so the preprocessor inserts:
#define UINT8 unsigned char
BOOL isCheckSumCorrect(const UINT8 *dataPointer, UINT8 len, UINT8 checkSumByte);
// GENERIC_TYPE_DEFS_H IS defined, so the preprocessor inserts nothing.
UINT8 encrypt(UINT8 c);
UINT8 decrypt(UINT8 c);
// GENERIC_TYPE_DEFS_H IS defined, so the preprocessor inserts nothing.
UINT8 generateCRC(const UINT8 *ptr, UINT8 Len);
BOOL isCRCValid(const UINT8 *ptr, UINT8 Len, UINT8 CRCChar);
main () { /* Do Stuff */ }
Дальнейшая предварительная обработка (не показана) копирует #define
по всему коду.
Вы гарантированно включите охрану, если будете учитывать другие предупреждения препроцессора и линтера
Линтер предупредит вас (ошибки 451 и 967), если в каких-либо .h
файлах отсутствуют стандартные элементы защиты. Компилятор предупредит о дублированных определениях символов, если в GenericTypeDefs.h
с несколькими включениями нет защитных элементов. Если этого не произойдет, либо создайте свой собственный MyGenericTypeDefs.h
, либо переключитесь на заголовок <stdint.h>
, который является частью стандарта C и обеспечивает функциональность, аналогичную вашей GenericTypeDefs.h
.
.
Предупреждение: плохой обходной путь вперед
Если вы действительно настаиваете на исправлении предупреждения вместо его игнорирования, вам придется удалить #include <GenericTypeDefs.h>
из каждого из .h
файлов и ввести его один раз, прежде чем один или несколько из этих файлов будут включены, например так:
checksum.c
#include <GenericTypeDefs.h>
#include "checksum.h"
cryptography.c
#include <GenericTypeDefs.h>
#include "cryptography.h"
crc.c
#include <GenericTypeDefs.h>
#include "crc.h"
main.c
#include <GenericTypeDefs.h>
#include "checksum.h"
#include "cryptography.h"
#include "crc8.h"
main () { /* Do Stuff */ }
Это не рекомендуется, так как это дает вам больше работы и больше шансов на ошибку (без обид, но вы только человек, а препроцессор - нет). Вместо этого просто попросите препроцессор выполнить свою работу и использовать защитные приспособления так, как они были спроектированы.