Объявление глобальных переменных в c.
Доброго времени суток! Извеняюсь за оффтоп, но больше спросить негде. Проблема в следующем: Один кусок программы пишется в файле client.c Для коммуникации в локальной сети к нему посредством #include "network.h" привязывается библиотека. В ней должна быть переменная int PORT. Если я сейчас объявляю в client.c extern int PORT; То линкер выплёвывает ошибку на манер - дважды декларированная переменная. То же самое происходит если в client.c это объявление не писать. Я так понимаю это мотому, что network.h дважды включается сначала в network.c и потом в client.c... Применение ifndef не помогло. Если прописать переменную в network.c а не в network.h то всё работает. Но по идее при написании client.c, network.c вовсе не обязан быть доступным, соответсвенно программер не может посмотреть какие переменные есть в network.c... Это можно как-нибудь побороть ? Т.е. декларировать переменню в network.h и чтобы линкер не плевался ? Заранее благодарен Владимир. signature.asc Description: Digital signature
Re: Объявление глобальных переменных в c.
Wladimir Krawtschunowsi -> debian-russian@lists.debian.org @ Fri, 5 May 2006 14:31:58 +0200: WK> Доброго времени суток! WK> Извеняюсь за оффтоп, но больше спросить негде. WK> Проблема в следующем: WK> Один кусок программы пишется в файле client.c WK> Для коммуникации в локальной сети к нему посредством WK> #include "network.h" WK> привязывается библиотека. В ней должна быть переменная int PORT. WK> Если я сейчас объявляю в client.c WK> extern int PORT; WK> То линкер выплёвывает ошибку на манер - дважды декларированная WK> переменная. То же самое происходит если в client.c это объявление не WK> писать. Я так понимаю это мотому, что network.h дважды включается WK> сначала в network.c и потом в client.c... Применение ifndef не WK> помогло. Если прописать переменную в network.c а не в network.h то WK> всё работает. Но по идее при написании client.c, network.c вовсе не WK> обязан быть доступным, соответсвенно программер не может посмотреть WK> какие переменные есть в network.c... WK> Это можно как-нибудь побороть ? Т.е. декларировать переменню в network.h WK> и чтобы линкер не плевался ? extern пишется в хедере. А без extern - в .c. Ровно одном. Вероятнее всего, в network.c. Но вообще так делать без КРАЙНЕЙ необходимости не рекомендуется. Разве что у тебя эта переменная - константа. -- Artem Chuprina RFC2822: Jabber: [EMAIL PROTECTED] kernel bug (англ.) - ядрёна вошь -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: WK> Переменная костанта(каламбур). Просто ещё один человек пишет WK> server и ему почему-то сильно не понравилось, когда я прописал WK> порт через define. Аргументацию я так и не понял... Может, лучше ему объяснить, что в C так *принято* делать? -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Friday 05 May 2006 15:21, Artem Chuprina wrote: > Но вообще так делать без КРАЙНЕЙ необходимости не рекомендуется. Разве > что у тебя эта переменная - константа. Это ещё почему? "КРАЙНЯЯ" необходимость может быть продиктована просто некоторым удобством решения конкретной задачи, мы ж не знаем что там за задача. А про религиозное "в программе не должно быть глобальных переменных" лучше не надо. Меня, например, напрягает передавать каждому объекту ссылку на объект, который ведёт лог программы. -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Friday 05 May 2006 23:20, Wladimir Krawtschunowsi wrote: > Ну здесь в принципе вопрос в здравом смысле. Чем меньше этих > переменных будет, тем лучше. Особенно если это не константа, и какая-то > функция догадается её поменять не сговариваясь с осталными, то ошибку > потом можно искать годами Но это не должно делать из глобальных > переменных табу. Кое-где они действительно очень удобны, если код не > вылазиет за рамки двух трёх тысяч строк. Программирование вообще не самая лёгкая профессия. Некоторый, для меня разумный минимум глобальных переменных у меня есть всегда. Например, конфиг программы. До 10-15 тыс строчек проблем не создавало, да и дальше вряд ли будет... -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
Anton Petrusevich -> debian-russian@lists.debian.org @ Fri, 5 May 2006 23:00:57 +0200: >> Но вообще так делать без КРАЙНЕЙ необходимости не рекомендуется. Разве >> что у тебя эта переменная - константа. AP> Это ещё почему? "КРАЙНЯЯ" необходимость может быть продиктована AP> просто некоторым удобством решения конкретной задачи, мы ж не знаем AP> что там за задача. А про религиозное "в программе не должно быть AP> глобальных переменных" лучше не надо. Меня, например, напрягает AP> передавать каждому объекту ссылку на объект, который ведёт лог AP> программы. Авторов юникса, видимо, тоже напрягало. Поэтому есть _функция_ syslog. В принципе, вообще в таких случаях стараются сделать именно функцию, которая возвращает нужное значение (указатель на объект, если надо). Тогда у тебя гарантированно скрыты детали реализации. А что бывает, когда так не делают сразу, можно посмотреть на примере "переменной" errno в случае с тредами. Проблему решили, конечно, но не могу сказать, чтобы решение было офигительно прямым... -- Artem Chuprina RFC2822: Jabber: [EMAIL PROTECTED] Танк - это не фаллический символ. Он просто _едет_... (С)энта -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On 05/05/06, Wladimir Krawtschunowsi <[EMAIL PROTECTED]> wrote: Доброго времени суток! Извеняюсь за оффтоп, но больше спросить негде. Проблема в следующем: Один кусок программы пишется в файле client.c Для коммуникации в локальной сети к нему посредством #include "network.h" привязывается библиотека. В ней должна быть переменная int PORT. Если я сейчас объявляю в client.c extern int PORT; То линкер выплёвывает ошибку на манер - дважды декларированная переменная. То же самое происходит если в client.c это объявление не писать. Я так понимаю это мотому, что network.h дважды включается сначала в network.c и потом в client.c... Применение ifndef не помогло. Если прописать переменную в network.c а не в network.h то всё работает. Но по идее при написании client.c, network.c вовсе не обязан быть доступным, соответсвенно программер не может посмотреть какие переменные есть в network.c... Это можно как-нибудь побороть ? Т.е. декларировать переменню в network.h и чтобы линкер не плевался ? Погоди, в чем проблема? По симптомам похоже, что в network.h у тебя переменная не объявляется (declare), а определяется (define). То есть, в network.h ты пишешь: int PORT; вместо extern int PORT; Вот пример как надо: === Makefile === test: test.o main.o = === test.h === extern int t; int test(); === === test.c === #include "test.h" int t=0; int test() { return t; } === === main.c === #include "test.h" main() { t=100; printf("%d=%d", test(), t); } -- BR, Stanislav
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 07:34, Artem Chuprina wrote: > Авторов юникса, видимо, тоже напрягало. Поэтому есть _функция_ syslog. Это камень в сторону ведения лога или организации программы? Если по организации программы, то откуда _функция_ возьмёт дескрипторы/имена файлов логов? Сохранит в статической области после инициализации? Так то фактически то же самое. Кроме того, логов может быть много. Ну и это только пример. Второй пример, приходящий в голову -- конфиг программы. Лежит объект MainServerConfig в области глобальных переменных, и вся программа знает что и как сконфигурировано. Третий пример можно придумать с объектом Listener, когда по условиям задачи он только один может быть, и из разных частей программы можно добавлять сокеты для прослушивания в ожидании данных. > В принципе, вообще в таких случаях стараются сделать именно функцию, > которая возвращает нужное значение (указатель на объект, если надо). Откуда данные у функции? Где-то должен храниться указатель на структуру данных для неё? Такая функция всего лишь один уровень косвенности даёт, что часто даже (в программах меньше 1 строк) и не нужно. > Тогда у тебя гарантированно скрыты детали реализации. А что бывает, > когда так не делают сразу, можно посмотреть на примере "переменной" > errno в случае с тредами. Тут проблема в том, что "изменилось ТЗ", когда систему в 1970-х придумывали, ни о каких тредах не было мыслей даже. В случае изменения ТЗ что б у тебя не было спроектировано, всегда можно придумать случай, когда в изменённых условиях придётся часть существенно перепроектировать. > Проблему решили, конечно, но не могу сказать, > чтобы решение было офигительно прямым... Кстати относительно безболезненно. Приходится только djbdns патчить... Я собственно к чему всё это говорю. Правило "не делать глобальных переменных" не должно быть религией, хотя его действительно стоит придерживаться. Но в таком случае оно становится "делать глобальных переменных разумно мало". -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
Anton Petrusevich -> debian-russian@lists.debian.org @ Sat, 6 May 2006 11:00:21 +0200: >> В принципе, вообще в таких случаях стараются сделать именно функцию, >> которая возвращает нужное значение (указатель на объект, если надо). AP> Откуда данные у функции? Где-то должен храниться указатель на AP> структуру данных для неё? Да. Только он static в пределах того файла, и кто попало в него писать не может. -- Artem Chuprina RFC2822: Jabber: [EMAIL PROTECTED] Даже у столовой ложки есть регламент - ее мыть положено. Если этот регламент не выполнять, рискуешь ботулизм заработать. (c)vitus -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 11:22, Artem Chuprina wrote: > AP> Откуда данные у функции? Где-то должен храниться указатель на > AP> структуру данных для неё? > Да. Только он static в пределах того файла, и кто попало в него писать > не может. С этим как раз проблем нет, "дайте нам указатель, можно дикий, и мы нагадим куда угодно". Проблема не писать куда писать не следует -- проблема дисциплины кодирования в рамках задачи. Проблему диких указателей это не решает :( -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: AP> С этим как раз проблем нет, "дайте нам указатель, можно дикий, и AP> мы нагадим куда угодно". Проблема не писать куда писать не AP> следует -- проблема дисциплины кодирования в рамках AP> задачи. Проблему диких указателей это не решает :( Нагадить в заранее известное место из благих побуждений гораздо проще, если до этого известного места можно легально добраться. -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: AP> Проблему диких указателей это не решает :( Зато это решение следует принципу минимума привилегй (по-моему ещё Дейтел его сформулировал, ссылку дать не могу), а также принципу разделения интерфейсов (Robert Martin, http://www.objectmentor.com/resources/articles/isp.pdf). -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 12:43, Alex Grigorovich wrote: > > Второй пример, приходящий в голову -- конфиг программы. Лежит объект > > MainServerConfig в области глобальных переменных, и вся программа > > знает что и как сконфигурировано. > Ровно до тех пор, пока в конструкторе MainServerConfig не захочется > что-нибудь залогировать; или наоборот -- пока конструктор логгера на > захочет узнать из конфигурации, куда собственно писать будем. Это все > про C++, конечно. Ну что за "сферические кони в вакууме"? Ничто не мешает сделать их всех правильно, чтобы конструкторы все отработали как надо, и в момент чтения/перечитывания конфига сказать логеру новую конфигурацию. -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: AP> Ну что за "сферические кони в вакууме"? Это, к сожалению, горькая истина. AP> Ничто не мешает сделать их всех правильно, чтобы конструкторы все AP> отработали как надо, и в момент чтения/перечитывания конфига AP> сказать логеру новую конфигурацию. И годами поддерживать это решение, постоянно давая по рукам новым членам команды, которые ещё не уяснили, что в данном месте имеется нехорошая зависимость от порядка инициализации глобальных переменных, и makefiles поэтому править не надо, а то компилятор переставит .o-шки местами? Проще уж всю такую байду завернуть в singleton или его подобие, и обложить mutex'ом функцию получения ссылки (раз уж DoubleLock больше не в моде). -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 17:21, Mikhail Gusarov wrote: > AP> Проблему диких указателей это не решает :( > Зато это решение следует принципу минимума привилегй (по-моему ещё > Дейтел его сформулировал, ссылку дать не могу), а также принципу > разделения интерфейсов (Robert Martin, > http://www.objectmentor.com/resources/articles/isp.pdf). /me чешет репу. Народ говорит о чём-то своём. Вот накинулись на тему глобальных переменных, и каждый ищет как их пнуть. Жаль, что DJB они не объясняли как программировать надо... Кстати, самому жутко как он пишет... -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 17:27, Mikhail Gusarov wrote: > И годами поддерживать это решение, постоянно давая по рукам новым > членам команды, Ох, давайте не будем про "новых членов команды", с "мозгами" бы разобраться... :) > которые ещё не уяснили, что в данном месте имеется > нехорошая зависимость от порядка инициализации глобальных переменных, А? Кто сказал что есть? Помимо конструкторов бывает ещё метод Init, который мы ручками зовём в нужном порядке. > и makefiles поэтому править не надо, а то компилятор переставит .o-шки > местами? /me чешет репу. никогда не занимался такой фигнёй. > Проще уж всю такую байду завернуть в singleton или его подобие, и > обложить mutex'ом функцию получения ссылки (раз уж DoubleLock больше > не в моде). Вариант. Ну спрячем мы указатель на объект в статическом методе объекта, примерно то же самое Артём Чуприна предлагает. Но наступления счастья, по сравнению с одним глобальным объектом, я не вижу. Всё то же самое, в общем-то, только вызывать менее удобно. -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: >> которые ещё не уяснили, что в данном месте имеется нехорошая >> зависимость от порядка инициализации глобальных переменных, AP> А? Кто сказал что есть? Помимо конструкторов бывает ещё метод AP> Init, который мы ручками зовём в нужном порядке. А вот кто сказал: -- > Ровно до тех пор, пока в конструкторе MainServerConfig не захочется > что-нибудь залогировать; или наоборот -- пока конструктор логгера на > захочет узнать из конфигурации, куда собственно писать будем. Это > все про C++, конечно. -- Не говоря уж о том, что Init() ручками - это ужос-ужос, и его нужно в RAII-обёртку пихать, а эту обёртку опять инициализировать. При Init() мы можем звать уже после глобальных конструкторов, а обёртку или после, или в непредсказуемом порядке. AP> Вариант. Ну спрячем мы указатель на объект в статическом методе AP> объекта, примерно то же самое Артём Чуприна предлагает. Но AP> наступления счастья, по сравнению с одним глобальным объектом, я AP> не вижу. Всё то же самое, в общем-то, только вызывать менее AP> удобно. "объект" реализует интерфейс (в общем смысле) очень обширный. Его операции включают и получение указателя/ссылки на объект, и явный вызов деструктора, и прочую байду типа конверсии типов, а это, опять-таки, нарушает принцип минимума привилегий: нет возможности чего-то легально сделать - нет проблемы, что кто-то это легально сделает. -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
On Saturday 06 May 2006 18:54, Mikhail Gusarov wrote: > А вот кто сказал: > -- > > Ровно до тех пор, пока в конструкторе MainServerConfig не захочется > > что-нибудь залогировать; или наоборот -- пока конструктор логгера на > > захочет узнать из конфигурации, куда собственно писать будем. Это > > все про C++, конечно. > -- Это сказал, кстати, не я :) > Не говоря уж о том, что Init() ручками - это ужос-ужос, и его нужно в > RAII-обёртку пихать, а эту обёртку опять инициализировать. При Init() > мы можем звать уже после глобальных конструкторов, а обёртку или > после, или в непредсказуемом порядке. Гм. Какой-такой "ужос-ужос", он нужен только тогда, когда порядок выполнения конструкторов играет роль. Это нужно для единиц объектов, как правило. > "объект" реализует интерфейс (в общем смысле) очень обширный. Его > операции включают и получение указателя/ссылки на объект, и явный > вызов деструктора, и прочую байду типа конверсии типов, а это, > опять-таки, нарушает принцип минимума привилегий: нет возможности > чего-то легально сделать - нет проблемы, что кто-то это легально > сделает. Мне бы такие проблемы... -- Anton Petrusevich -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
You ([EMAIL PROTECTED]) wrote: ПК> Ребята, Вы, мне кажется, о вкусах спорите. Си он тем и ПК> отличается, что одну задачу можно решить большим количеством ПК> "правильных" способов. А вот у кого какой стиль это уже вещь ПК> интимная. Обсуждение уже шло по поводу правильности предлагаемых способов, причём не только в контексте того, что что-то написано и работает, но и ушло в контекст поддержки написанного (почему я и затронул принципы разделения ответственности). -- JID: [EMAIL PROTECTED] -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]
Re: Объявление глобальных переменных в c.
Ребята, Вы, мне кажется, о вкусах спорите. Си он тем и отличается, что одну задачу можно решить большим количеством "правильных" способов. А вот у кого какой стиль это уже вещь интимная. Кстати, я всегда удивляюсь, на что способен программер, когда его за живое заденут :). Так ещё пару недель и эта тема (изначальный вопрос которой уже давно решели :) побьёт все рекорды. Ещё кстати, оптимизация кода это конечно хорошо, но по моему личному опыту она не всегда того стоит, так как процесс этот может по времени превосходить написание самой программы. -- Покотиленко Костик <[EMAIL PROTECTED]> -- To UNSUBSCRIBE, email to [EMAIL PROTECTED] with a subject of "unsubscribe". Trouble? Contact [EMAIL PROTECTED]