|
Вопрос # 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
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|