2011-11-29 8 views
1

Каков правильный способ структурирования заголовков? Есть некоторые аналогичные вопросы, но никто не дает хорошего ответа. Сейчас я использую это:Правильная структура заголовка C

#ifndef INCLUDE_FILENAME 
#define INCLUDE FILENAME 

/* Includes */ 

/* Constants, enums */ 

/* Structure */ 

/* Globals */ 

/* Function prototypes */ 

#include "File.c" 

#endif 

I then # включить заголовок из программы.

У этого есть много проблем с необходимостью включать вещи в правильном порядке, и я уверен, что это неправильная структура.

В идеале он должен работать при создании единого файла и создании модулей отдельно.

Связанный вопрос: Должны ли реализованы глобальные переменные в заголовке или определены как внешние и реализованы в исходном файле?

+2

Почему вы определяете макрос INCLUDE как FILENAME? :) – Nobody

+3

На самом деле вы включаете исходные файлы в заголовочные файлы, как показано в вашем примере? Это, как правило, неодобрительно, поскольку это может привести к проблемам с несколькими определениями. – Nate

+0

Никто и Нейт не ударили ноготь по голове. –

ответ

3

В идеале заголовочный файл не должен определять какие-либо данные или код. Это означает, что глобальные значения должны быть только объявлены в заголовке, а затем определены в исходном файле.

Цель файла заголовка - дать подсказки компилятору, а не содержать фактические данные и код.

Кроме того, исходные файлы не предназначены для включения вообще, каждый исходный файл обычно передается непосредственно компилятору.

+1

, чтобы уточнить для OP, который, кажется, является новичком: переменная _declared_ в файле заголовка, используя ключевое слово 'extern'. он _defined_ в соответствующем исходном файле, повторяя ту же декларацию, но не указывая ключевое слово 'extern'.(хотя использование глобальной переменной довольно дискуссионно) –

+2

Чтобы объявить, но не определить глобальную переменную, поставьте перед ним ключевое слово «extern». Это говорит компилятору «есть символ этого типа с этим именем в другом компиляторе». Или еще лучше ограничить прямой доступ к глобальному компилятору, в котором он определен. Используйте вызовы функций для доступа к ним из других устройств. –

+0

@AdrienPlisson: избили меня до 20 секунд. –

0

Это вопрос вкуса, вы должны только убедиться, что все объявлено или указано вперед, прежде чем они будут использованы, что зависит от вашего кода.

И вы обычно не включаете #include.c в заголовки.

1

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

Вот пример, взятый из Wikepdia, о том, как он используется:

#pragma once 

struct foo 
{ 
    int member; 
}; 

Вместо:

#ifndef GRANDFATHER_H 
#define GRANDFATHER_H 

struct foo 
{ 
    int member; 
}; 

#endif /* GRANDFATHER_H */ 

Я думаю, что это гораздо более уборщик подход ...

Согласно Wikipedia , эта директива поддерживается также в Clang, Comeau C/C++, Digital Mars C++, GCC, компилятор Intel C++, Microsoft Visual Studio Так на практике Это довольно портативный ... :)

+0

Является ли '#pragma once' во втором примере ошибкой или я что-то не понимаю об этом шаблоне? –

+0

@EdwardThomson, ты прав, моя ошибка. Сейчас я отредактирую – stdcall

Смежные вопросы