Přeos globálních proměnných mezi svěma soubory v projektu? – C / C++ – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

Přeos globálních proměnných mezi svěma soubory v projektu? – C / C++ – Fórum – Programujte.comPřeos globálních proměnných mezi svěma soubory v projektu? – C / C++ – Fórum – Programujte.com

 
Hledat
Vybavení pro Laser Game
Spuštěn Filmový magazín
Laser Game Brno
Pergoly a střechy Brno

Aja
~ Anonymní uživatel
2 příspěvky
27. 1. 2017   #1
-
0
-

Mám možná začátečniclou otázku k C.

Řekněme, že v projektu psaném v C máme soubor main.c a v kteérm je smotná funkce min() a také je v něm definovaná globální proměnná int timer.

Zároven je v projektu druhý soupor třeba casovac.c. v něm potřebujeme pracovat s globalní proměnnou timer .

Globlní proměnná je sice ltná napříč všemi funkcemi ,ale zároveň jen  funkcemi v jednom souboru a já nevím jak timer správně dostat jako globání do casovac.c

Doufám, že jsem popsal dostatečně srozumitelně o co mi jde.

Děkuji za radu.

Nahlásit jako SPAM
IP: 162.247.72.–
Staon0
Návštěvník
27. 1. 2017   #2
-
+1
-
Zajímavé
Kit +

Jestli dobře rozumím problému, tak v souboru casovac.c potřebujete deklaraci: 

extern int timer;

Tu byste, samozřejmě, měl mít v hlavičce, ne ji ručně dopisovat do každého modulu.

Nicméně, základní pravidlo pro používání globálních proměnných je "nikdy je nepoužívat". Nevím, co řešíte, ale jsem si téměř jistý, že máte špatně návrh.

Nahlásit jako SPAM
IP: 94.142.234.–
27. 1. 2017   #3
-
0
-

#2 Staon
nikdy neříkej nikdy. Pokud dělá v C embeded software pro jednočip, tak to dokonce může být nejlepší přístup.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Staon0
Návštěvník
27. 1. 2017   #4
-
0
-

#3 hlucheucho
Hmm, máte nějaký konkrétní praktický příklad? Připadá mi, že používat C na platformě, kde je problém si předat jeden argument do funkce, nějak ztrácí význam.

Nahlásit jako SPAM
IP: 94.142.234.–
Hansa0
Duch
27. 1. 2017   #5
-
0
-

~~Extern , došlo mi to ihned jak jsem viděl odpověď, už mi asi měkne mozek, předtím jsem o tom přemýšlel snad hodinu a nemohl si vzpomenou ani správně nadefinovat dotaz na google.
V každém případě děkuji.
Máte pravdu je to strukturálně špatně, ale jak píše Staon v embended se to bere jinak.
Nicméně, když jsme narazili na návrh budu konkrétně nekonkrétní.
Je to z embended světa konkrétně ARM Cortex M světa, jeden možná dnes největší výrobce těchto procesorů (aktuálně má na trhu přes 880 různých provedeni v Cortex M0 až M7. ke svým procesorům nabízí sw, v kterém lze „naklikat“ základní konfigurací jako jsou hodiny, definovat konfiguraci IO, nastavit časovače, přerušení DMA atd. Zkrátka takovou tu nudnou část, pak to umí vygenerovat celý projekt včetně C kódu pro vše naklikáné.  Docela hezká věc, pro typický středně složitý procesůrek to může byt mnoho set až tisíc řádek kódu, s kterým se nemusíte patlat. Problém je, že celá tato část se vygeneruje jako jeden soubor main.c v kterém třeba pro časovač bude funkce static void MX_TIM1_Init(void) v které se komplet neinicializuje časovač, třeba jako PWM výstup s DMA kanálem pro proud dat z paměti na výstup. Doposud, snad jasné a přehledné. Nicméně onen časovač tam není pro nic za nic a může třeba generovat hodiny pro nějaký externí ADC převodník (berme to čistě jako příklad a nepitvejme to)
Doposud byla běžná praxe, všechny funkce tykající se onoho extrního ADC byly v souboru ADC.c a tam bylo vše od void ADC_Init(void), která mino jiné dělal i to co void MX_TIM1_Init(void) až po ReadADC(), která vyčítala data z ADC . Důvodem byla a je přehlednost. Při přenesení ADC do jiného projektu stačilo vložit ADC.c a upravit ADC_Init() na nový hw.
To co řeším jak to skloubit s novým generátorem od výrobce, který funkci pro inicializaci časovače MX_TIM1_Init(void) vrazí do main.c ?
Přesunout jí ručně do ADC.c není dobrý nápad, protože onen sw pro generování inicializace lze použít vícekrát i v průběhu projektu třeba na dogenerování něčeho co se zapomnělo, změnilo atd. došlo by tedy znovu k vygenerování nové MX_TIM1_Init(void) v main.c a bylo by to nepřehledné. Další možnost by bylo předávat funkcím v ADC ukazatel na časovač jako parametr, ale nevim zda je to vhodné nebo z ukazatele na časovač udělat externí globální proměnnou, ideální asi není nic z toho, jde spíše o to najít nejméně blbé řešení. :-)
 

Nahlásit jako SPAM
IP: 188.92.9.–
Aja
~ Anonymní uživatel
2 příspěvky
27. 1. 2017   #6
-
0
-

 

Koukám, že jsme odpověděl z kolegovo PC a tak odpověd dorazila jako od Hansa i když jsme se pat ze svého jako Aja

Nahlásit jako SPAM
IP: 164.132.51.–
27. 1. 2017   #7
-
0
-

#4 Staon
Použití C na takové platformě význam má pro usnadnění práce programátora, ale má své omezení. Na jednočipech se parametry často předávají přes registry, ale i tak s tím nějaká režije je. Navíc ne každý parametr lze přes registry předat, např float. Pak by se navíc musela použít paměť které nebývá nazbyt. Další prostor pro využití globální proměnné je při obsluze přerušení. Taková funkce je pak striktně bez parametrů a s návratovým typem void. Nějak se pak data mezi obsluhou přerušení a hlavním programem předat musí. Do třetice je zápis nastavení do EEPROM: jedna část programu provádí čtení a používá zvolené hodnoty, jiná část programu, dalo by se říct autonomní, provádí komunikaci s uživatelem a uložení hodnot. V takovém případě je nejdůležitější aby se uživatelem nastavená hodnota uložila na stejné místo, ze kterého ji bude hlavní program číst. Zde je globální proměnná mnohem šikovnější (do paměti ji umisťuje překladač, menší riziko chyby) než programátorem pevně určená adresa (chvíle nepozornosti při úpravě kódu a celý systém se zhroutí). Pokud programátor respektuje vlastnosti použitého jednočipu a vývojového prostředí, je C nebo i C++ velice výkonným nástrojem.  Koneckonců každý nástroj lze používat špatně, dobře nebo i mimořádně efektivně.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Staon0
Návštěvník
27. 1. 2017   #8
-
0
-

#7 hlucheucho
Tady jsme si asi měli nejdříve nadefinovat, o čem se bavíme. Globální proměnnou jsem měl na mysli skutečně proměnnou, ke které si různé části kódu svévolně přistupují. To je to, co nikdy nepoužívat. Vaše příklady ale do tohoto ranku nepatří.

V přerušení potřebujete předat data mezi handlerem a vnějším kódem (podobnou situaci musíme řešit i my na "velkém" systému v handlerech signálů). Tam vám stačí proměnnou pomocí static omezit pouze na modul, ve kterém je handler a funkce, které s daty pracují. Zbytek programu o takové proměnné absolutně nemusí (nesmí) vědět.

V případě konfigurace dokonce vůbec globální proměnnou nechcete, pouze chcete řídit, kde v paměti bude umístěná. Osobně, pokud bych něco takového dělal, bych si konfigurační proměnné umístil do struktury, tu bych zinstancioval tam, kde ji chci mít, a pak všem funkcím, které s konfigurací pracují, předával ukazatel na ni.

Nahlásit jako SPAM
IP: 94.142.234.–
Staon0
Návštěvník
27. 1. 2017   #9
-
0
-

#5 Hansa
No, z popisu nejsem příliš moudrý :-)

Pokud vás k používání globálních proměnných nutí vygenerovaný kód, tak pochopitelně s tím nic neuděláte. Pak stále platí, že máte chybu v návrhu, akorát jste ji neudělal vy, ale autoři generátoru :-)

Za předpokladu, že generovaný kód není špatně, nevidím na vašem popisu nic, co by nutilo používat globální proměnné. Z mého pohledu bych viděl zásadní chybu ve vašem tvrzení "void ADC_Init(void), která mino jiné dělal i to co void MX_TIM1_Init(void)". Pokud vám generátor vygeneruje inicializaci timeru, tak byste ji měl použít a ne ji duplikovat někde jinde.

Jako objektáři mi váš problém moc složitý nepřijde. Odkaz na timer se nějakým způsobem injektuje do ADC, ten si ho uschová a následně s ním pracuje. Nevěřím, že jeden uložený ukazatel je takový paměťový problém, aby to ve vašem případě nešlo udělat. Osobně mám zkušenost s Xilinxovým Spartanem, a tam to problém nebyl. Ale pochopitelně se můžu mýlit a být překvapený :-)

Nahlásit jako SPAM
IP: 94.142.234.–
27. 1. 2017   #10
-
0
-

Globální proměnnou definují učebnice jazyka přesně. Definici rozumím tak, že je k ní přístup z celého programu bez ohledu na to, zda je celý program v jednom souboru či více souborech. Pokud budu mít ve dvou souborech stejně pojmenovanou proměnnou, při kompilaci každého souboru samostatně nevznikne problém, ten vznikne v okamžiku, kdy zkusí z těchto dvou části složit výslednou aplikaci. A tak je překladači potřeba nějak "vysvětlit", že se nejedná o duplicitu, že je to ta samá proměnná. K tomu slouží extern.

Konfigurace v EEPROM: každá část programu tu samou hodnotu musí najít na stejném místě. Pokud hlavní program bude v hlavni.c a prijeti hodnot od uživatele v nastaveni.c tak globální proměnná je nejčistší způsob. V každém ze souborů si proměnnou pro uložení této hodnoty pojmenovat jinak a umístit ji fyzicky na stejnou adresu EEPROM sice může projít, ale nese sebou ryziko chyb zejména při editaci kódu. Takové rozdělení na dva soubory (někdy i více souborů) zlepšuje přehlednost, je to takové primitivní rozdělení na objekty kde lze každou z těch částí programovat samostatně. Použití modifikátoru static nedává žádný smysl, překladač má pro EEPROM speciální modifikátory.

Přerušení: opět případ globální proměnné. Obsluha přerušení nevidí dovnitř žádné funkce, ani main. Je vhodné použít modifikátor volatile aby překladač četl obsah paměti. Bez tohoto modifikátoru překladač optimalizuje a může se stát, že skutečný obsah proměnné, kterou pozměnila asynchronní událost - přerušení nepřečte. Modifikátor static je vhodný pro lokální ukazatele polí např. při práci s UART. Kvůli přehlednosti často dávám obsluhy přerušení do samostaného souboru.

Ještě jeden příklad globálních proměnných jsem nezmínil. Jsou to registry procesoru.

Nezažil jsem, že by se funkce, byť to byl nějaký init, nevracela za místo volání. Ale je to jen zkušenost s Atmel Software Frameworkem na AVR.

Pokud je ADC spouštěn časovačem, často se to děje hardwarově - nastavení je pak zapsáno v příslušných registrech převodníku a časovače. V takovém případě je šikovnější číst to přímo z těchto registrů a aby to bylo strozumitelnější, napsat si makra, která to vytáhnou. Pokud je potřeba pak ještě něco změnit, používá se read - modify přístup aby se nesáhlo do jiného nastavení v tom samým registru, opět se na to často používají makra nebo inline funkce. Některé funkce frameworku se takto nechovají, někdy stačí volat je ve vhodném pořadí, většinou je lepší si takové funkce napsat sám.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
KIIV
~ Moderátor
+43
God of flame
27. 1. 2017   #11
-
0
-

#2 Staon
Globalni promenne maji nekdy svoje opodstateneni. Zakazat je uplne nedava smysl. Viz: http://wiki.c2.com/?GlobalVariablesAreBad. Ostatne v C mas spousty globalnich promennych jako stdin, stdout, stderr, errno (toto je uz vetsinou thread local), ... U jednocipu se nekdy pocita kazda instrukce, kazdej byte ramky, takze je rozdil mezi 10 urovnema wrapperu (kazda uroven zabere desitky bajtu a desitky instrukci), aby to vypadalo pekne - a nebo jednou globalni promennou. Ne kazdy si na blikani diodou koupi Core i7 na 3+GHz, aby pak rozjel na nekolika gigabajtech javu, ktera jednou za sekundu zmeni stav...

Kazdopadne ani nema smysl psat pro jednocipy v Assembleru, protoze pak clovek pise to same velice vyrazne dele, nez kdyz to nacvaka v C za pul hodky. A vysledek je vetsinou lepsi, nez kdyz se to zacatecnik pokusi napsat v ASM. Opet je tu vyjimka - casti kodu, kde je casovani naprosto kriticke. V C se neda zarucit, jestli pak vyjdou instrukce presne jak maji.

----------

Jinak je to same, jako oblibene heslo:

Premature optimization is the root of all evil.

Coz vesmes vyustilo v "Nikdy nic neoptimalizovat, udela se to az se zjisti, ze je s tim problem". Nicmene tohle pravidlo je vytrzene z kontextu. Cele bylo totiz:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

Kdyz se program napise uplne blbe, tak uz to proste pozdeji zoptimalizovat nejde, protoze se to musi zahodit a napsat znovu poradne.

Nahlásit jako SPAM
IP: 94.113.99.–
Program vždy dělá to co naprogramujete, ne to co chcete...
Staon0
Návštěvník
8. 2. 2017   #12
-
+1
-
Zajímavé
Kit +

#10 hlucheucho
Problém globálních proměnných není v tom, že jsou v globálním datovém segmentu (koneckonců i stack a halda jsou obvykle v tom samém segmentu, takže principiálně je každá proměnná globální), ale v jejich přístupnosti kdekoliv jinde. To je to, co je špatně. A to je to, o čem se bavím.

Pokud před proměnnou mimo funkci napíšete static, říkáte tím, že se jedná o proměnnou, jejíž viditelnost je omezena pouze na modul, ve kterém je deklarovaná. Tudíž můžete mít v každém modulu stejně pojmenované proměnné, aniž by došlo ke kolizi při linkování. To je ideální řešení, pokud potřebujete vytvořit proměnnou v globálním segmentu a zároveň nevytvořit globální proměnnou. Ideální řešení pro handler přerušení nebo signálů.

Váš příklad s globálním přístupem ke konfiguraci v EEPROM se zhroutí jak domeček z karet v okamžiku, kdy váš zaměstnavatel přijde s požadavkem, že pokud váš program dokáže nějakou věc dělat jednou, tak přece bude strašně jednoduché, aby ji dělal i dvakrát a vy budete nucen vytvořit v EEPROM druhou instanci konfigurace. Řešení je takové, jak jsem psal minule - vytvořit konfigurace v globálním segmentu a do zbytku programu distribuovat ukazatel na ně. Vaše podmínky jsou splněné - překladač si určil adresu sám a zbylý kód je zcela nezávislý na konkrétní hodnotě.

Nahlásit jako SPAM
IP: 94.142.234.–
Staon0
Návštěvník
8. 2. 2017   #13
-
+1
-
Zajímavé
Kit +

#11 KIIV
Samozřejmě, nijak nepopírám, že se jedná o heuristické pravidlo. Ale to pravidlo je pravdivé v 99 % případů a ten zbytek jsou dost speciální věci. A přístup embedářů "u nás je to přece jinak, pro nás taková pravidla nemají smysl" je chyba.

Konkrétně z vašich příkladů. errno je letitá ostuda standardní knihovny, za kterou se její autoři stydí, a která na vícevláknových systémech musí být řešená nějakým zpraseným mechanismem v překladači. Rozhodně se nejedná o příklad dobře použité globální proměnné.

stdout a spol. jsou v principu singletony. Singletony jsou obecně zlo. Což poznáte přesně v okamžiku, kdy se pokusíte napsat první automatický test kódu, který k singletonu přistupuje. Např. pokud budete chtít otestovat, zda váš kód generuje správný výstup, zjistíte, že jste v koncích. A bude před vámi dlouhá a protivná práce, kdy si do daných funkcí přidáte argument FILE* a stdout budete přepisovat na něj.

Osobně bych si představoval, že stdout bude součástí kontextu, který program dostává jako argument funkce main. Tak to není, takže asi není lepší způsob, než ho mít jako globální proměnnou. Ale používat ho globálně problém je a programátor by se tomu vyhýbat měl.

Když už jste zmínil premature optimization, tak globální přístup k proměnné je právě krystalická ukázka. Ano, může se časem ukázat, že předávání proměnných program zpomaluje, a pak se uchýlit ke globálnímu přístupu. Ale skutečně pouze v případě, že to má smysl.

Nevím, jestli chápu vaše tvrzení "když se program napíše úplně blbě..." Úplně blbě napsaný program je právě obvykle důsledek předčasných optimalizací a je to přesně ten důvod, proč je nedělat a jsou považované za "root of all evil". Pokud to ovšem někdo používá jako výmluvu pro nedělání optimalizací, které nekazí návrh (od detailů jako používat reference místo kopie objektů až po výběr algoritmů s vhodnou složitostí), pak je to pochopitelně špatně.

Nahlásit jako SPAM
IP: 94.142.234.–
8. 2. 2017   #14
-
0
-

Proměnná umístěná mimo jakoukoliv funkci je proměnnou globální a defaultně je static, proto se tam většinou static nepíše, stejně tak proměnné uvnitřtř funkce jsou defaultně auto. Nenapadá mne, jak by se autovariable použila jako globální a ani jsem to nezkoušel takovou udělat. Naproti tomu static uvnitř funkce, tedy lokální, jsem použil několikrát, přesto byla viditelná (logicky) jen uvnitř funkce. Taková proměnná si pak pamatuje stav z předchozího volání funkce, nezaniká po jejím návratu. Předávání ukazatelů nemusí být nutně správnou cestou. Jak napsal KIIV, představuje to režii, která může být vražebná. Právě jednočipy jsou typickým příkladem, kde se požadavky na zapouzdření, předávání referencí nebo alespoň ukazatelů často dostávají do rozporu s možnostmi hardware a užitnými vlastnostmi produktu. U bateriových přístrojů každá instrukce navíc nebo jejich provádění rychleji znamená zkrácení života baterií, v realtime systémech prodlužuje odezvu na událost. Pak je ještě faktor ekonomický - jestli ten procesor bude o 10 hal. dražší, bude problém (platí ve velkosériové výrobě) a tak programátor to musí udělat tak aby mu to spolehlivě běželo i na jednodušším méně výkonném procesoru s menší pamětí. Pak si musí programátor některé "parádičky" odpustit a trochu víc si dávat pozor na to, co dělá.

Puristické dodržování pravidel v reálném světě nikdy moc neobstálo. Každé pravidlo má svou vyjímku, často je třeba udělat kompromis. A někdy platí "v jednoduchosti je síla" byť to není křišťálově čistý kód.

Pokud to programátor napíše blbě, předání ukazatele, zapouzdření atd. to nespasí - holt sračka zůstane sračkou. Naproti tomu s rozumem použitá globální proměnná může usnadnit práci a/nebo zjednodušit řešení. A opět jsme u lidského faktoru. Pravidla a globální proměnné jsou nástroje, každý z nich lze použít dobře nebo špatně.

Ještě jedna drobnost: když si šéf postaví hlavu, tak mu sebeblbější koncept nevymluvíš. Pak máš jen dvě možnosti: 1. udělat a skousnout pocit nesmyslné a marné práce. 2. odejít

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Staon0
Návštěvník
15. 2. 2017   #15
-
0
-

#14 hlucheucho
Proměnná definovaná mimo funkci s modifikátorem static nesplňuje vaši definici "že je k ní přístup z celého programu bez ohledu na to, zda je celý program v jednom souboru či více souborech," tudíž podle ní není globální. Její extent je samozřejmě globální (jako u každé statické proměnné), ale její scope nikoliv - ten je omezený pouze na daný soubor. A modifikátor static se k nim obvykle právě z tohoto důvodu píše.

Proměnná nebo funkce s modifikátorem static má nastavený internal linkage,tzn. dané symboly nelze linkovat odjinud než ze stejného modulu. Default bez modifikátoru je external linkage, tedy vzniká globálně viditelný symbol. Se static tak můžete mít v různých modulech stejně pojmenované proměnné nebo funkce bez kolizí. Bez static by kolize vznikly.

Tímto debatu končím, protože už mne nebaví se hádat s někým, kdo ani napodruhé nebyl schopen si otevřít Google a ověřit si, jestli náhodou nemluvím o něčem, co dosud neznal. Přitom stačí jednoduše kouknout třeba na wiki: https://en.wikipedia.org/wiki/Static_variable

Nahlásit jako SPAM
IP: 94.142.234.–
15. 2. 2017   #16
-
0
-

Dotaz byl jak v C něco udělám. Pokud dva nebo více souborů .c nazvu moduly, pak int cislo umístěné mimo jakoukoliv funkci ve dvou a více modulech povede k chybě při linkování. Teprve když int cislo je jen v jednom jediném modulu a v ostatních je extern int cislo, pak vše proběhne správně. Použití static nic neřeší, má vliv jen na "životnost" proměnné, nezviditelní tuto proměnnou jinde. Pokud ve dvou a více modulech použiju static int cislo, opět linker ohlásí chybu. Tuto situaci jsem zažil mockrát když jsem s C začínal. Použití static spolu s extern pak může vést k chybě. Když už jsme u té Wikipedie, podívej se na příklady https://en.wikipedia.org/wiki/Global_variable .

Jak vznikl extern? Bylo potřeba rozlišit stavy, kdy si dva spolupracující programátoři nerozumněli a ve svých modulech pojmenovali stejně proměnné jejichž funkce byla i diametrálně odlišná a naproti tomu kdy se dva programátoři domluvili na použití globální proměnné použitelné v obou jimi vytvářených modulech. A tak se pro druhý případ zavedlo klíčové slovo extern aby takto domluvení programátoři dali linkeru najevo svou vůli. (Poněkud jsem si ten příběh zdramatizoval, ale faktem je, že bylo potřeba takovou proměnnou vidět mezi moduly a odlišit to od nechtěného použití identifikátoru)

S nástupem objektových jazyků se situace změnila. Některé konstrukce téměř vymizely, static se chová jinak než v C ... S tímto jsem si naběh v C#, kde statická členská proměnná třídy je viditelná ve všech instancích třídy. Objektové jazyky zcela změnily přístup - proměnnou a funkce které s ní pracují jsou uvnitř jakéhosi objektu, je mnohem širší možnost řídit jejich viditelnost a život. Současně pak bylo potlačeno použití globálních proměnných. Cílem bylo programování "polidštit" a aspoň trochu ho učinit blbuvzdorným.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Staon0
Návštěvník
16. 2. 2017   #17
-
0
-

#16 hlucheucho
Tahle diskuze začíná být poněkud surrealistická. Na začátku jsem chtěl, abyste mi dal reálné příklady, kdy je vhodné použít globální proměnnou (komentář 4). Vy jste několik příkladů uvedl (komentář 7) a já jsem vám dva ze tří oponoval (obsluha prerušení, konfigurace v EEPROM), že ve skutečnosti globální proměnnou nepotřebujete, ale stačí vám proměnná s rozsahem platnosti na modul (komentář 8). Od té doby je vaše argumentace zcela chybně, pravděpodobně proto, že nechápete význam klíčového slova static u proměnné mimo funkci. Domnívám se tak, protože vaše tvrzení

Pokud ve dvou a více modulech použiju static int cislo, opět linker ohlásí chybu.

je špatně! Než mi napíšete další chybnou odpověď vycházející opět ze stejného chybného předpokladu, vyzkoušejte si následující: 

static1.c:

#include <stdio.h>

static int cislo = 1;

void module1(void) {
  printf("%d\n", cislo);
}

static2.c:

#include <stdio.h>

static int cislo = 2;

void module2(void) {
  printf("%d\n", cislo);
}

main.c:

void module1(void);
void module2(void);

int main(int argc_, char* argv_[]) {
  module1();
  module2();
  return 0;
}

$ gcc -o static main.c static1.c static2.c
$ ./static
1
2

Pokud oba static odstraníte, linker začne hlásit kolizi. Toto není novinka v C++, to je vlastnost, kterou má C skoro odjakživa. A ve vašem zdramatizovaném příběhu o vzniku extern je první popisovaná situace (stejné proměnné v různých modulech) chyba programátorů - právě že nepoužili static.

Koukněte se např. na tyto zdrojáky mallocuhttps://code.woboq.org/userspace/glibc/malloc/malloc.c.html a najděte si např. proměnnou main_arena nebo funkci _int_malloc. Proč myslíte, že tam static je? To jste se s tímto nikdy nesetkal?

Nahlásit jako SPAM
IP: 94.112.135.–
16. 2. 2017   #18
-
0
-

Pouze jsem popsal zkušenost, kterou jsem v minulosti získal metodou pokus - omyl. Potom jsem důsledně používal unikátní identifikátory a u proměnných které měly být "vidět všude" extern. Nakolik jsou moje zkušenosti svázané s konkrétním kompilerem a linkerem a jehich konkrétní verzí, zda to nedoprovázela jiná začátečnická chyba už asi těžko zjistím. 2x nevstoupíš do stejné řeky - vývoj šel dál, staré vývojové prostředky zmizely v propadlišti dějin a já už taky nedělám všechno stejně.

Procházel jsem jen examples které dávají k IDE a Application Notes od výrobců jednočipů. Na takový postup jsem tam nenarazil. I když to mohla být jen štábní kultura, byl to pro mne vzor, jak to dělat.

hu

Nahlásit jako SPAM
IP: 195.178.67.–
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 15 hostů

Moderátoři diskuze

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032021 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý