| 
| 
 | Вопрос # 5 060/ вопрос открыт / | 
 |  Доброго времени суток, уважаемые эксперты!чистый С без ++.
 есть 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 (статус: 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™ (статус: Доктор наук), 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 (статус: 1-ый класс), 2 марта 2011, 14:50 [#2]:Сделал как написал Вадим К 
 появилась ошибка
 Unresolved extern 'buf'	test.c
 |  
|   | 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 (статус: 1-ый класс), 2 марта 2011, 15:19 [#6]:то же самое - убирание extern unsigned char buf[];
 не помогло
 |  
|   | 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 (статус: 1-ый класс), 2 марта 2011, 17:12 [#10]:нет, так тоже не получается. спасибо, буду копать далее в направлении моего компилятора. |  
|   | 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
 |  Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте. |