Начинаю работать в Eclipse и компилирую файл main.c всё компилируется, всё нормально. Но хочется простого хомячьего комфорта. И хочется некоторые куски исходного текста держать в отдельных файлах и чтобы препроцессор (или кто там) просто сводил все мелкие файлы перед компиляцией обратно в большой и громоздкий main.c, не пытаясь откомпилировать эти файлики по отдельности до объединения всего исходного текста и ругаясь, мол unknown type name ‘uint32_t’ part101.c Существует ли нормальная директива типа #just_include_and_shut_up для препроцессора? Или, может, в Eclipse есть что-нит такое.
Отслеживать
задан 23 апр 2018 в 13:51
Alexey Ershov Alexey Ershov
Нет смысла. Лучше разбивать на несколько .c-файлов.
23 апр 2018 в 13:53
Есть. Файлы бывают .h и .c , вот имееноо .h — нужны для сборки всего проэкта, а .с нужен для «реализации» (например в obj). Но при этом проэкт должен состоять из «модулей», и каждый модуль должен ссылаться на один .с файл, а .h файл не должен содержать кода (или данных для дата-сегмента) вообще. А вот как правильно настроить eclipse что б он сие понимал — не подскажу.
5. Язык Си: как разделить код на модули
23 апр 2018 в 14:04
Директива для этого, думаю, не нужна. Нужно правильно скомпоновать (сконфигурировать) проэкт. Из директив понадобится только три #ifndef module1_h #define module1_h #endif .
23 апр 2018 в 14:10
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
#include делает ровно то, что Вам нужно — вставляет содержимое файла. Очень часто (например в бусте) делают куски кода в файлах с расширением imp или inl, куда и вставляют код. А потом их подключают через #include «func.imp» и так далее. Зачем нужно такое расширение? потому что некоторые IDE (например, эклипс) пытаются проявить интеллект и компилировать файл, если у него расширение c или cpp.
Такие include можно делать многократно вложенные, главное, не рекурсивные (тогда нужно уже защищать через ifndef-define-endif).
Если эклипс будет дальше бузить — переходите на те редакторы, которыео нормально к подобному относятся, к примеру vim/emacs.
Отслеживать
ответ дан 23 апр 2018 в 14:16
112k 6 6 золотых знаков 91 91 серебряный знак 158 158 бронзовых знаков
У вас слишком размытый вопрос, но если своими следующими словами я вам как-то помог, то это прекрасно 🙂
О, философия подъехала
Если он , действительно, у вас такой, то это значит, что вы и есть хомяк 😀 что у вас либо нет функций, либо их мало, либо они есть, но очень плохо реализованы, либо что-то в совокупности.
А решение этой ‘громоздкости’ только одно : создавать функции, чётко представляя свою предметную область, то есть сначала считать ножки на стульях, а потом количество костей на ногах бабушек-сноубордистов не нужно.
Когда вы решите этот вопрос, и получите негромоздкий main.c , то вам нужно будет правильно это всё распределить по вашей(-им) директории(-ям). Недавно мы решали подобную проблему, по которой вы можете ‘пробежаться’ вот здесь.
Язык Си с нуля — Урок 47 — Многофайловые проекты. Создание и подключение. Заголовочные файлы.
По моему личному опыту скажу, что в «Си» лучше соответствовать следующему шаблону : 1 предметная область — 1 файл с .c -расширением + 1 с .h -расширением. Если вы представляете свою сложную задачу, как несколько маленьких, то вы вполне можете делать несколько c-файлов и заголовочных файлов (но не переусердствуйте).
И вот только на этом моменте я ,скорее всего, понял вашу проблему.
Допустим, что сама команда для компиляции у вас правильная.
Представим ситуацию, что :
- У вас 1 заголовочный файл chairs.h , в котором находятся определения структур, прототипов функций и т.д.
- chairs.c , в котором находятся сами функции, которые должны быть связаны с определениями из chairs.h . А ещё у вас есть main.c , в котором вы подключили заголовочный файл chairs.h , но всё равно ничего не компилируется,верно?
chairs.h нужно подключить в самом chairs.c , и тогда проблем с компиляцией у вас не должно возникнуть.
Не бойтесь что-то подключать в любой .c -файл. Если в двух файлах с реализациями ваших функций (например, те же main.c и chairs.c ) вы подключаете один и тот же заголовочный файл стандартной библиотеки, то препроцессор всё равно не позволит из-за своего include guard работать лишний раз с копиями (почитайте про include guard, чтобы у вас при создании заголовочного файла не было проблем) 🙂
Если у вас всё сделано так же, как я описал выше , и у вас всё равно какие-то проблемы, то это означает, что вы либо сделали что-то не так, как я вас направил, и вам для полного «разжёвывания» нужно просто смотреть примеры, как это делают другие.
Будете искать ответы на такие вопросы, как у вас на данный момент, то станете хомяком компилятор будет сам вас затыкать, как сейчас, потому что u’ve done it wron’, но он вам помогает 🙂
А unknown type name ‘uint32_t’ part101.c означает, что у вас в файле part101.c не узнаётся такой тип, который определён в . Значит, вам нужно подключить туда этот самый заголовочный файл, либо подключить пользовательский заголовочный файл, в котором находится (зависит от случая).
Источник: ru.stackoverflow.com
Как правильно разделить Си проект на файлы?
Всем привет! Вопрос крайне дилетантский: есть ли какие-то рекомендации/требования/правила по созданию архитектуры проекта? Подключать .h файлы нужно в .c или .h? Какое количество extern переменных уже считать «плохим»? и тд
Если более локально: у меня есть два .с и два .h файла. Каждый из них использует перекрестные переменные. Хочу все оформить так, чтобы было читабельно и логично.
- Вопрос задан более трёх лет назад
- 925 просмотров
Решения вопроса 1
C++ почти с рождения
Ну как минимум использование перекрестных переменных уже нелогично. Лучше функциями это обернуть. Как бы инкапсулировать в модуль.
Правильный способ это на бумаге нарисовать модули/объекты системы и обозначить как они взаимодействуют между собой и внешним миром. И уже исходя из этого разбивать. В идеале чем больше модуль похож на черный ящик тем лучше с точки зрения системности.
Как лакмусовая бумажка может использоваться то, что из одного модуля вдруг надо копаться в кишках другого, или знать о том как там что-то реализовано.
Как пример именно для Си — стандартная библиотека. Открываешь файл получаешь указатель на структуру FILE но тебе, абсолютно не важно какие там поля, создается она по malloc или заранее созданный объект из некоего массива таких объектов. Это уже скрыто реализацией. Есть функции которые работают с этим указателем и всё.
Как плохой пример «не очень черного ящика» можно рассмотреть strtok строка которая передается на вход будет модифицироваться и портится, что может быть не очевидным из семантики. Но сделано в угоду скорости и использования памяти.
Ответ написан более трёх лет назад
Нравится 3 2 комментария
Источник: qna.habr.com
Как разбить программу на файлы си
static int shoulder = 0 , scaling = — 100.0 , left_right = 0.0 , up_down = 60.0 , i = 0 , j = 0 , x = 0 , y = 0 ;
static int shoul = 0 ;
class place <
float x , y ;
float xU , yU ;
float xD , yD ;
public:
place ();
place ( float x , float y );
void print();
inline int get_xU () ;
inline int get_yU () ;
inline int get_xD () ;
inline int get_yD () ;
friend void spit ( place a , transation b );
friend void spit ( transation a , place b );
>;
void place ::print() <
glPushMatrix ();
glTranslatef ( left_right , up_down , scaling );
glRotatef (( GLfloat ) shoulder , 0.0 , 1.0 , 0.0 );
glRotatef (( GLfloat ) shoul , 1.0 , 0.0 , 0.0 );
glTranslatef ( x , — y , 0.0 );
GLUquadricObj * disk1 = gluNewQuadric ();
gluDisk ( disk1 , 0 , 5 , 20 , 16 );
glTranslatef ( 0.0 , 0.0 , — 2.0 );
GLUquadricObj * disk2 = gluNewQuadric ();
GLUquadricObj * cilinder = gluNewQuadric ();
gluCylinder ( cilinder , 5 , 5 , 2 , 20 , 16 );
gluDisk ( disk2 , 0 , 5 , 20 , 16 );
glPopMatrix ();
>
Заголовочный файл к нему:
static int shoulder = 0 , scaling = — 100.0 , left_right = 0.0 , up_down = 60.0 , i = 0 , j = 0 , x = 0 , y = 0 ;
static int shoul = 0 ;
class transation <
float x , y ;
float xU , yU ;
float xD , yD ;
public:
transation () < x = 0 ; y = 0 ;>
transation ( float x , float y );
void print();
inline int get_xU () ;
inline int get_yU () ;
inline int get_xD () ;
inline int get_yD () ;
friend void spit ( place a , transation b );
friend void spit ( transation a , place b );
>;
transation :: transation ( float x , float y ) <
this -> x = x ; this -> y = y ;
xU = this -> x ; yU = — this -> y + 0.75 ;
xD = this -> x ; yD = — this -> y — 0.75 ;
>
void transation ::print() <
glPushMatrix ();
glTranslatef ( left_right , up_down , scaling );
glRotatef (( GLfloat ) shoulder , 0.0 , 1.0 , 0.0 );
glRotatef (( GLfloat ) shoul , 1.0 , 0.0 , 0.0 );
glTranslatef ( x , — y , 0.0 );
glScalef ( 1.0 , 0.1 , 0.1 );
glutSolidCube ( 15 );
glPopMatrix ();
>
Заголовочный файл к нему:
Класс, который инициализирует объекты первых двух классов
#include
#include «Place.h»
#include «Transation.h»
#include «Petri_Net.h»
using namespace std ;
class petri_net <
int step , step1 , step2 , stepi , stepj ;
int i , j ;
int ** tab1 , ** tab2 ;
public:
petri_net ( int i , int j );
/*инициализация объектов*/
void petri_net :: build () <
place a ( 2.0 , 8.0 );
transation b ( 5.0 , 58.0 );
a .print();
b .print();
spit ( a , b );
>
Загаловочный файл к нему:
#include «Place.h»
#include «Transation.h»
Источник: www.programmersforum.ru