Отговори на тема  [ 47 мнения ]  Отиди на страница 1, 2, 3, 4  Следваща
глобални променливи в С 
Автор Съобщение
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Яну 01, 2012 7:04 pm
Мнения: 2581
Местоположение: Велико Търново / София
Мнение глобални променливи в С
Играя си тука със Code Blocks - правя конзолна програма на чисто С. Компилатора пише, че е GNU GCC.
Понеже е по-голяма програмата реших да я направя на няколко файла main.h main.c dop.h и dop.c
Искам да дефинирам едни променливи в main.h и да се виждат от всички функции.
във dop.c имам include "main.h" и include "dop.h" . Същото и във main.c
Дотук всичко работи добре. Проблема възниква когато във main.h реша да задам първоначална стойност на променливата, тогава ми изкарва съобщение multiple definition of `promenlivata'. Принципно мога да си задам първоначалната стойност във main() функцията, но така ми е по-удобно и прегледно. Не мога да разбера какво бъркам.
Интересното е, че програма написана по същия начин във MplabX - XC8 не дава такива грешки.
Направих и една проба написах static promenlivata = 0; така ми го приема, но интересното е че като я ползвам във main.c то от dop.c като и променям стойността тя не се променя :|

_________________
https://github.com/slav4ocom/


Чет Дек 26, 2019 9:34 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Ное 06, 2018 4:18 pm
Мнения: 1188
Мнение Re: глобални променливи в С
декларираш променливата във всички модули, в main я декларираш както си му е реда а в останалите модули слагаш extern пред променливата за да укажеш че вече си я декларирал в друг модул.


Чет Дек 26, 2019 9:41 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 25, 2012 8:14 am
Мнения: 4574
Местоположение: Новата земя на племето Мутум'ба
Мнение Re: глобални променливи в С
По принцип е лоша практика да се инициализират променливи в хедъра. Аз мога да потвърдя че Code Blocks не го пуска това

_________________
'просто' е технически синоним на 'красиво'


Пет Дек 27, 2019 11:12 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 8:22 am
Мнения: 15501
Местоположение: София
Мнение Re: глобални променливи в С
Начи не е зле малко да прочетеш що е то област на видимост, както и какъв е точно замисъла на "static", "extern", "const", "volatile". Ама да го прочетеш и да го разбереш!

Това е крайъгълен камък в С, особенно за embedded. А се оказва, че доста "програмисти" имат бяло петно по темата. А като намесим и думички като stack и heap.... нещата съвсем отиват в киреча.

Н'бабане Гт'муан'га написа:
По принцип е лоша практика да се инициализират променливи в хедъра. Аз мога да потвърдя че Code Blocks не го пуска това


И откъде на къде няма да го допуска? Това не нарушава правилата? Дали е красиво е тема на друг разговор.

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Пет Дек 27, 2019 11:14 am
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Вто Ное 06, 2018 4:18 pm
Мнения: 1188
Мнение Re: глобални променливи в С
Нбабане е прав, не може да задаваш начални стойности в хедъра. Може да си направиш списък от константи в хедъра и една функция в main.c която да се изпълнява еднократно в началото и която присвоява тези константи към променливите ти. Така или иначе имаш такава функция, която конфигурира микроконтролера ти - входове/изходи, цифрови/аналогови портове и т.н. Променливите обикновенно са резервирани клетки от RAM паметта, на която не можеш да програмираш начални стойности.


Пет Дек 27, 2019 12:32 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 8:22 am
Мнения: 15501
Местоположение: София
Мнение Re: глобални променливи в С
Bai Ui написа:
Нбабане е прав, не може да задаваш начални стойности в хедъра.


И защо да не може? Кое точно правило на ANSI С ще нарушиш?

Пак да повторя, не споря дали е красиво или не. Просто не виждам, защо да не може?

Хедъра си е най-обикновен фаил, който се включва по съдържание 1:1. Т.е. дали ще се казва ".h", ".c" или ".бай Хуй" и какво има в него - на компилатора му е все тая. Той просто ще плесне съдържанието му, на мястото на include"" и толкоз. Ако хедъра се инклудва само на едно място, какъв е проблема да има дефиниция, декларация и инициализация на глобални променливи в него?

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Последна промяна Цецо на Пет Дек 27, 2019 1:19 pm, променена общо 2 пъти



Пет Дек 27, 2019 1:17 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10356
Местоположение: Добрич
Мнение Re: глобални променливи в С
slav4o.com написа:
Искам да дефинирам


В Ц/Ц++ има две думички - дефиниция и декларация. Дефиницията създава някакво животно, а декларацията само казва на компилатора, че има такова животно и няма нужда да псува.
Животните могат да са най-различни - променливи, константи, структури, класове, шаблони... В зависимост от животното декларацията и дефиницията се правят по различен начин. Примерно при променливите разликата между декларация и дефиниция е, че пред първото трябва да има extern. При функциите декларацията е без тяло и т.н.

Дефиницията обикновено е една и се прави на едно място. При чисто Ц повече от една дефиниция е възможна, само ако са weak животни. При Ц++ някои животни могат да се овърлоадват, което не е точно множествени дефиниции, но почти... Възможно е също да няма нито една дефиниция, в случаи че се прави библиотека или пък животното е дефинирано в линкер скрипта. Но това са примери за изключения. В общия случай дефиницията е една и е в някой с/срр файл.
Тук е мястото да припомня, че компилатора бачка "на парче". Парчето е един сорс файл (към който предварително са вмъкнати хедърите) и това се нарича compilation unit (компилируема единица или както там се превежда). В един проект може да има много сорс файлове (единици), но всяка единица се компилира сама за себе си, независимо от останалите. И за всяка единица се получава обектен файл. После идва ред на линкера, който взема обектните файлове и сглобява междинна библиотека или краен изпълним файл (някакъв, какъвто му кажеш).
Та реално линкерът се занимава с дефинициите, дали са повече или по-малко от необходимото. Компилаторът в общия случай го интересува дали има декларации. Когато срещне дефиниция, компилатора генерира сивмолите, данни, код или там каквото съдържа дефиницията и резултатът отива в обектния файл. Важно е да се знае, че когато се компилира дадена дефиниция, може да има значение дали преди дефиницията е имало декларация или не. Това е така, защото дефиниции без декларации и без изрично указани област на видимост/валидност се считат за локални в текущата единица. "Локални" може би не е точния термин. Истинските локални животни са статичните (static) и те имат съществена разликата. Докато дефинициите без декларация нямат видими разлики. Изглеждат си съвсем като глобални, но с дребната подробност че когато са в библиотеки и не се ползват в рамките на библиотеката може да бъдат "оптимизирани". Затова е добра практика винаги да си има и декларация, дори да е само една компилируема единица.
Та с две думи, най-добрата практика е за всяко нещо (различно от статично) да си има една декларация в хедъра и евентуално дефиниция в сорса, като сорса и хедъра е добре да са с едно и също име.
Tова е въпрос на добра практика... иначе за компилатора няма значение кое е хедър, кое е сорс. Те се сглобавят в един общ файл преди да стигнат компилатора. Така че всеки може да си пръска нещата където си иска. Но ако не искаш да те псуват колегите, добре е да се спазват обичаите...


Пет Дек 27, 2019 1:18 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Сря Яну 26, 2005 1:01 pm
Мнения: 1952
Местоположение: Варна
Мнение Re: глобални променливи в С
Цецо написа:
Bai Ui написа:
Нбабане е прав, не може да задаваш начални стойности в хедъра.


И защо да не може? Кое точно правило на ANSI С ще нарушиш?

Пак да повторя, не споря дали е красиво или не. Просто не виждам, защо да не може?

Хедъра си е най-обикновен фаил, който се включва по съдържание 1:1. Т.е. дали ще се казва ".h", ".c" или ".бай Хуй" и какво има в него - на компилатора му е все тая. Той просто ще плесне съдържанието му, на мястото на include"" и толкоз. Ако хедъра се инклудва само на едно място, какъв е проблема да има дефиниция, декларация и инициализация на глобални променливи в него?

Цецо, не става въпрос за това дали нещо пречи на препроцесора да "плясне" съдържанието на файл който е вмъкнат с #include.
Вероятно това което обърква Славчо е защо подобен сорс се компилира, когато не използва extern при декларацията на глобалните променливи дефинирани в друг сорс.(защо няма грешка за дублирани имена на променливи когато ги "дефинира" в хедър файл).
И после, защо слагайки инициализация при "дефиницията" на променлива в хедър файл вмъкнат в няколко сорс файла, билда му се чупи.
Добрата практика е хедър файловете *.h (*.balhui може да се ползва като се пише нещо на коляно в гаража)да съдържат интерфейс към другите сорс файлове за това там се поставят декларации а не "дефиниции". Дефинициите се поставят в сорс файловете *.c
Не че препроцесора няма да "плясне" всичко, което му дадеш.
Както се казва, "Езикът C, дава достатъчно въже за да се простреляш в крака." :D
В случая на Славчо с CodeBlocks мисля че C сорс файлове биват подавани на C++ компилатор. И заради това няма конфликт на имена на променливи в първия случай(глобални променливи "дефинирани" в хедър файл инклуднат на няколко места), заради name mangling. Заради name mangling в двата сорс файла всъщност Славчо получава две отделни променливи. Вместо една с интерфейс към други файлове, обекти.
Но когато Славчо сложи инициализация в хедъра, неговите "дефиниции" стават дефиниции и се стига до конфликт предполагам при линкване.

_________________
Най-опасният враг на истината и свободата е мнозинството.


Нед Дек 29, 2019 9:20 am
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пон Сеп 27, 2004 8:22 am
Мнения: 15501
Местоположение: София
Мнение Re: глобални променливи в С
Zdrav, никога не съм твърдял, че е красиво, а, че не противоречи на правилата. От тая гледна точка ми е много чудно, как едно IDE, би ми забранило да го направя. Не познавам Code Blocks, но ми се струва странно да има подобни ограничения, както каза Бабане... От там тръгна всичко.

Апропо, за мен използването на extern е грозничко, защото скапва енкапсулацията и прави кода спагетообразен. Пак с уговорката, че не е забранено, но това си е нещо като goto... върви го търси де е дефинирано и кой от къде го пипа...На йерархията и се такова, таковата...

_________________
"Да еба и шибаната държава" мислеше си Гошо, докато се опитваше да улучи кофата за боклук от балкона на осмия етаж.


Нед Дек 29, 2019 1:47 pm
Профил ICQ
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Чет Фев 03, 2005 1:21 am
Мнения: 10573
Местоположение: София
Мнение Re: глобални променливи в С
Цецо написа:
...Апропо, за мен използването на extern е грозничко, защото скапва енкапсулацията и прави кода спагетообразен. Пак с уговорката, че не е забранено, но това си е нещо като goto... върви го търси де е дефинирано и кой от къде го пипа...На йерархията и се такова, таковата...

А как трябва да се организира кода за да не се използва extern?


Нед Дек 29, 2019 2:21 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пон Мар 13, 2006 12:59 pm
Мнения: 3855
Местоположение: Габрово
Мнение Re: глобални променливи в С
Ке се намеся: pure functions: https://en.wikipedia.org/wiki/Pure_function


Нед Дек 29, 2019 2:38 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Пет Юни 03, 2005 8:39 pm
Мнения: 1954
Мнение Re: глобални променливи в С
Според мен в *.h файловете трябва да има само инфо, което се обработва от препроцесора - константи, прототипи и т.н. - неща не изискващи заделяне на памет. Всички инициализации, начални стойности, т.е. тези, за които се заделя памет трябва да са в *.c файловете. Винаги се придържам към тези правила и никога нямам проблеми, каквито има колегата.
Не виждам проблем с extern - на компилатора му е все тая дали е красиво или не :)

_________________
Определянето стойността на дадена величина се нарича ИЗМЕРВАНЕ!


Нед Дек 29, 2019 5:43 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Ное 12, 2004 2:38 pm
Мнения: 9103
Местоположение: Chicago, IL
Мнение Re: глобални променливи в С
syscop написа:
Не виждам проблем с extern - на компилатора му е все тая дали е красиво или не :)

Не е проблема в красотата (въпреки, че и тя е важна), а както казва Цецо в енкапсулацията, което пък води до евентуални проблеми и по-трудното им откривне/дебъгване. В проекти за мигалки тия неща нямат кой знае какво значение, ама в големи проекти са важни, а в някои области даже кода няма да може да се сертифицира. Та човек като свикне така и после тоя навик трудно се коригира.


Нед Дек 29, 2019 6:13 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог

Регистриран на: Нед Фев 26, 2006 5:52 pm
Мнения: 10356
Местоположение: Добрич
Мнение Re: глобални променливи в С
Пак да повторя... за всяка гобална променлива трябва да има декларация с extern. Няма друг начин да се укаже linkadge-a. А това е важно, защото някой ден вие или някой друг ще реши да направи кода библиотечен и ще има псувни.
За локалните променливи пък трябва да има static в дефиницията, декларацията не е необходима.
Ако няма нито static в дефиницията нито extern (декларация) се получава нещо средно между риба и рак. Уж е глобален обект за компилатора, ама за линкера си е с internal linkage... Не знам защо стандарта позволява подобна недомислица, аз навремето си мислех че е бъг на gcc, но се оказа, че е така по стандарт...


Нед Дек 29, 2019 6:24 pm
Профил
Ранг: Форумен бог
Ранг: Форумен бог
Аватар

Регистриран на: Пет Ное 12, 2004 2:38 pm
Мнения: 9103
Местоположение: Chicago, IL
Мнение Re: глобални променливи в С
Идеята беше да не се прави всяка променлива глобална.


Нед Дек 29, 2019 6:36 pm
Профил
Покажи мненията от миналия:  Сортирай по  
Отговори на тема   [ 47 мнения ]  Отиди на страница 1, 2, 3, 4  Следваща

Кой е на линия

Потребители разглеждащи този форум: 0 регистрирани и 3 госта


Вие не можете да пускате нови теми
Вие не можете да отговаряте на теми
Вие не можете да променяте собственото си мнение
Вие не можете да изтривате собствените си мнения
Вие не можете да прикачвате файл

Търсене:
Иди на:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.
Хостинг и Домейни