Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 5 060

Раздел: C++
/ вопрос открыт /

Доброго времени суток, уважаемые эксперты!
чистый С без ++.
есть 4 файла:

 
//файл test.c
#include "ProcUnit.c"
#include "ProcUnit2.c"
#include "ProcUnit3.c"
 
void main() {
  extern unsigned char buf[];
  buf[0] = 1;
  proc1;
  proc3;
  proc5;
}

 
//файл ProcUnit.c
#include "ProcUnit3.c"
 
void proc1()
{
  extern unsigned char buf[];
  buf[0] = 1;
  proc5;
}
 
void proc2()
{
}

 
//файл ProcUnit2.c
void proc3()
{
}
 
void proc4()
{
}

 
//файл ProcUnit3.c
unsigned char buf[12];
 
void proc5()
{
}
 
void proc6()
{
}

последний файл содержит переменную и функции, которые могут использоваться из любых других файлов. Пока этот файл подинклюден только к одному из файлов - все ок. Когда к 2м и более, как в примере, пишет мне что buf, proc5, proc6 redefined. И я не совсем тогда понимаю как правильно сделать. исходя из http://egbrv.3dn.ru/06_/h16.htm этого мануала, у меня все вроде правильно. Подскажите где ошибка.

AlexMPEI Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: AlexMPEI (статус: 1-ый класс)
Вопрос отправлен: 2 марта 2011, 13:19
Состояние вопроса: открыт, ответов: 2.

Ответ #1. Отвечает эксперт: Вадим К

Здравствуйте, AlexMPEI!
Тут скрытая ошибка. Дело в том, что хотя и можно писать так
#include "ProcUnit.c"
и даже так
#include "ProcUnit.html"
но смысла нет.
include на самом деле делает только одно - просто вставляет содержимое файла в указанную позицию. И не более.
Поэтому, когда файлы скомпилируются, то получается, что в разных .o файлах находятся одинаковые функции/переменные. Линковщик такое слинковать не может. Вот он и ругается.
наиболее правильно сделать так.
К каждому файлу делаем header файл. В другие c файлы включать нужно только header файлы.

//файл test.c
#include "ProcUnit.h"
#include "ProcUnit2.h"
#include "ProcUnit3.h"
 
void main() {
  extern unsigned char buf[];
  buf[0] = 1;
  proc1;
  proc3;
  proc5;
}

//файл ProcUnit.h
#ifndef ProcUnit
#define ProcUnit
#include "ProcUnit3.h"
 
void proc1();
void proc2();
#endif


//файл ProcUnit.c
#include "ProcUnit3.h"
 
void proc1()
{
  /* extern unsigned char buf[]; это уже тут не нужно. у нас ведь есть include! */
  buf[0] = 1;
  proc5;
}
 
void proc2()
{
}

//файл ProcUnit2.h
#ifndef ProcUnit2
#define ProcUnit2
void proc3();
void proc4();
#endif


//файл ProcUnit2.c
void proc3()
{
}
 
void proc4()
{
}

 
//файл ProcUnit3.h
#ifndef ProcUnit3
#define ProcUnit3
extern unsigned char buf[12]; /* а тут только указание компилятору, что переменная объявлена в другом месте. */
 
void proc5();
void proc6();
#endif

 
//файл ProcUnit3.c
unsigned char buf[12]; /* тут переменная реально объявлена */
 
void proc5()
{
}
 
void proc6()
{
}
Делать хедеры для всех файлов не обязательно и выносить из них все функции и переменные тоже не нужно. Только то, что нужно к использованию в других файлах.

Ответ отправил: Вадим К (статус: Академик)
Время отправки: 2 марта 2011, 13:34
Оценка за ответ: 5

Комментарий к оценке: детальный и подробный ответ

Ответ #2. Отвечает эксперт: min@y™

Здравствуйте, AlexMPEI!
Директива препроцессора #include "имя_файла" просто тупо вставляет на своё место содержимое этого файла непосредственно перед компиляцией. Это и надо учитывать. Программа с точки зрения компилятора - это один список строк. Естественно, если ты инклудишь один и тот же файл 2 раза, компилятор пробежится по нему 2 раза, обнаружив дубликаты имён функций и переменных.

Я избегаю такие ситуёвины вот так:

#define ProcUnit3_c // <---- !
 
//файл ProcUnit3.c
unsigned char buf[12];
 
void proc5()
{
}
 
void proc6()
{
}
//файл ProcUnit.c
#ifndef ProcUnit3_c // <---- !
  #include "ProcUnit3.c" // <---- !
#endif // <---- !
 
void proc1()
{
  extern unsigned char buf[];
  buf[0] = 1;
  proc5;
}
 
void proc2()
{
}

Ответ отправил: min@y™ (статус: Доктор наук)
Время отправки: 2 марта 2011, 13:41
Оценка за ответ: 5

Комментарий к оценке: простое решение проблемы

Мини-форум вопроса

Всего сообщений: 11; последнее сообщение — 2 марта 2011, 17:24; участников в обсуждении: 3.
min@y™

min@y™ (статус: Доктор наук), 2 марта 2011, 13:34 [#1]:

Директива препроцессора #include "имя_файла" просто тупо вставляет на своё место содержимое этого файла непосредственно перед компиляцией. Это и надо учитывать. Программа с точки зрения компилятора - это один список строк. Естественно, если ты инклудишь один и тот же файл 2 раза, компилятор пробежится по нему 2 раза, обнаружив дубликаты имён функций и переменных.

Я избегаю такие ситуёвины вот так:
#define ProcUnit3_c // <---- !
 
//файл ProcUnit3.c
unsigned char buf[12];
 
void proc5()
{
}
 
void proc6()
{
}
//файл ProcUnit.c
#ifndef ProcUnit3_c // <---- !
  #include "ProcUnit3.c" // <---- !
#endif // <---- !
 
void proc1()
{
  extern unsigned char buf[];
  buf[0] = 1;
  proc5;
}
 
void proc2()
{
}
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
AlexMPEI

AlexMPEI (статус: 1-ый класс), 2 марта 2011, 14:50 [#2]:

Сделал как написал Вадим К

появилась ошибка
Unresolved extern 'buf' test.c
min@y™

min@y™ (статус: Доктор наук), 2 марта 2011, 15:06 [#3]:

Цитата (AlexMPEI):

Unresolved extern 'buf' test.c

Значит ты не скармливаешь линкеру какой-то файл.
Делаю лабы и курсачи по Delphi и Turbo Pascal. За ПИВО! Пишите в личку, а лучше в аську. А ещё лучше - звоните в скайп!
Вадим К

Вадим К (статус: Академик), 2 марта 2011, 15:09 [#4]:

ну там странная процедура main. как то я ее не досмотрел.
Вот так она должна выглядеть
void main() {
  buf[0] = 1;
  proc1;
  proc3;
  proc5;
}
Галочка "подтверждения прочтения" - вселенское зло.
Вадим К

Вадим К (статус: Академик), 2 марта 2011, 15:17 [#5]:

Но вот только что попробовал - gcc скопмилировал оба варианта процедуры main
Галочка "подтверждения прочтения" - вселенское зло.
AlexMPEI

AlexMPEI (статус: 1-ый класс), 2 марта 2011, 15:19 [#6]:

то же самое - убирание
extern unsigned char buf[];
не помогло
AlexMPEI

AlexMPEI (статус: 1-ый класс), 2 марта 2011, 15:21 [#7]:

может правда это косяк моей среды - я использую mikroC
Вадим К

Вадим К (статус: Академик), 2 марта 2011, 15:45 [#8]:

все может быть. я такого компилятора не знаю и не знаю, что он может, а что нет.
Галочка "подтверждения прочтения" - вселенское зло.
Вадим К

Вадим К (статус: Академик), 2 марта 2011, 15:50 [#9]:

возможно ему понравится вот такое
//файл ProcUnit3.h
#ifndef ProcUnit3
#define ProcUnit3
extern unsigned char buf[];
 
void proc5();
void proc6();
#endif
Галочка "подтверждения прочтения" - вселенское зло.
AlexMPEI

AlexMPEI (статус: 1-ый класс), 2 марта 2011, 17:12 [#10]:

нет, так тоже не получается. спасибо, буду копать далее в направлении моего компилятора.
AlexMPEI

AlexMPEI (статус: 1-ый класс), 2 марта 2011, 17:24 [#11]:

вот так все линкуется:

//файл test.c
#include "ProcUnit.h"
#include "ProcUnit2.h"
#include "ProcUnit3.h"
 
void xxx()
{
  buf[0] = 1;
}
 
void main()
{
  proc1;
  proc3;
  proc5;
  xxx;
}

не линкуется только когда пытаюсь использовать buf внутри main

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 22 февраля 2025, 11:31
Выполнено за 0.05 сек.