LPCxpresso: Potize s optimalizaci

Milan B. milan na bastl.sk
Čtvrtek Červenec 28 00:33:28 CEST 2016


Starobylé skúsenosti aj mne vždy hovorili, že dve definície tej istej 
premennej by mali viesť k duplicitným symbolom. Prekvapilo ma, že u gcc 
je to úplne potichu akceptované.

Dodržiavanie pravidiel je samozrejmé, ale ak človek prevezme cudzí 
projekt (alebo sa vráti k starému), môže sa stať, že sa s menom 
premennej trafí do existujúcej...

Len pre kompletnosť, u gcc dávam do pozornosti prepínač -fno-common, 
ktorý chovanie kompilátora  vhodne upraví.

-m-



On 28. 7. 2016 0:19, Miroslav Šinko wrote:
> Zaujimave, toto by som na zaklade svojich skusenosti nevedel. Tak som 
> si to vyskusal s Windows kompilatormi, ktore tu a teraz mam: MSVC2005 
> Express a stary BC++ 5.02. Vysledky su rozne, pre moje lepsie 
> pochopenie som Vase zdrojaky rozsiril:
> ==== a1.c
> int premenna;
>
> void setp1 (int v)
> {
>         premenna = v;
> }
>
> int getp1(void)
> {
>     return premenna;
> }
>
> ==== a2.c
> int premenna;
>
> void setp2 (int v)
> {
>         premenna = v;
> }
>
> int getp2(void)
> {
>     return premenna;
> }
>
> ==== a0.c
> #include <stdio.h>
>
> extern int premenna;
>
> void setp1 (int v);  //tu som externy vymazal ako nadbytocne
> void setp2 (int v);  //vysledok to neovplyvnilo
> int getp1(void);
> int getp2(void);
>
> int main()
> {
>         premenna = 1;
>         printf ("%d\n", premenna);
>         setp1 (10);
>         printf ("%d\n", premenna);
>         setp2 (20);
>         printf ("%d\n", premenna);
>
>         printf ("%d %d %d\n", premenna, getp1(), getp2());
>
>         getchar();
>         exit(0);
> }
>
> =====
> kompilacia a linkovanie na oboch kompilatoroch len s warningom na exit 
> a v BC aj na chybajuci return value z main, oboje nepodstatne.
>
> Vysledky:
>
> MSVC2005
> --------
> 1
> 10
> 20
> 20 20 20
>
> t.j. ako u Vas v GCC. map subor obsahuje jediny vyskyt
> 0004:00000584       _premenna                  00417584 <common>
>
> BC++5.02
> --------
> 1
> 1
> 20
> 20 10 20
>
> t.j. ako som mal v pamati zo starych cias (ved ten kompiler tam patri 
> :-) ), ze kazda kompilacna jednotka ma vlastne premenne:
> 0003:00000000      @B2_1
> 0003:00000000      _premenna
> 0003:00000004      @B3_1
> 0003:00000004      _premenna
>
> Byt na pozore pred nedefinovanym spravanim, ako pisal Wek, je namieste.
> Osobne sa riadim presne ako tu viackrat preslo: jedna definicia 
> premennej v x.c, jedna deklaracia extern v x.h.
>
> Inac ten stary Borland ma defaultne vypnuty linker warning na 
> duplikatne symboly, po zapnuti napise:
> Warning: Public symbol '_premenna' defined in both module 
> O:\M_BC5\TEST_GLOBAL_VARIABLE\A2.OBJ and 
> O:\M_BC5\TEST_GLOBAL_VARIABLE\A1.OBJ
>
> miro
>
>
> On 27.7.2016 22:04, Milan B. wrote:
>> On 27. 7. 2016 14:29, Jan Waclawek wrote:
>>>> su ludia ktorych chyta
>>>> hroza ked v .h subore vidia deklaraciu niecoho co alokuje pamat
>>> Deklaracia niecoho co alokuje pamat sa nazyva definicia (C99 6.7.#5).
>>> Pouzivanie tohoto pojmu zjednodusuje a zjednoznacnuje veci.
>>>
>>> Je to dobry zvyk, lebo tak nealokujes tu pamat omylom viackrat. Nejde
>>> o tu
>>> pamat ale o vzajomnu viditelnost tych viackrat alokovanych veci z 
>>> roznych
>>> modulov.
>>
>> Tú pamät nenaalokujem viackrát ani keby som ako veľmi chcel a vždy
>> uvidím tú istú premennú.
>>
>> Je to tak trochu zrada - viacnásobná definícia globálnej premennej v
>> rôznych súboroch ma úplne rovnaký efekt či ju striktne v jednom súbore
>> definujem (bez extern) a v ostatných deklarujem (s extern) - bude
>> alokovaná len raz. Podmienkou je, že musí byť definovaná aspoň raz.
>>
>> V nasledujúcom príklade by človek intuitívne očakával, že linker vyhlási
>> chybu na tému duplicitnej premennej... no nestane sa tak, všetky
>> definície sa považujú za definície tejže premennej. (technicky sa
>> globálne premenné umiestňujú do sekcie COMMON (ďakujeme, FORTRAN) a
>> linker s nimi príslušne naloží).
>>
>> V norme sa tiež brble niečo ako "If the declaration of an identifier for
>> an object has file scope and no storage-class specifier, its linkage is
>> external." a krátko predtým "each declaration of a particular identifier
>> with external linkage denotes the same object or function"
>>
>> To samozrejme prináša iné nepríjemnosti. Ak omylom vo väčšom projekte
>> zadefinujem dve rôzne (významovo) premenné náhodou pod tým istým menom,
>> o probléme sa nedozviem a nebudem sa stačiť diviť, prečo majú premenné
>> podivné hodnoty.
>>
>> ==== a1.c
>> int premenna;
>>
>> void setp1 (int v)
>> {
>> premenna = v;
>> }
>>
>> ==== a2.c
>> int premenna;
>>
>> void setp2 (int v)
>> {
>> premenna = v;
>> }
>>
>> ==== a0.c
>> #include <stdio.h>
>>
>> extern int premenna;
>>
>> extern void setp1 (int v);
>> extern void setp2 (int v);
>>
>> int main()
>> {
>> premenna = 1;
>> printf ("%d\n", premenna);
>> setp1 (10);
>> printf ("%d\n", premenna);
>> setp2 (20);
>> printf ("%d\n", premenna);
>>
>> exit(0);
>> }
>>
>> $ gcc -Wall -o a a0.c a1.c a2.c
>> $ ./a
>> 1
>> 10
>> 20
>>
>> -m-
>>
> _______________________________________________
> HW-list mailing list  -  sponsored by www.HW.cz
> Hw-list na list.hw.cz
> http://list.hw.cz/mailman/listinfo/hw-list



------------- další část ---------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 3810 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://list.hw.cz/pipermail/hw-list/attachments/20160728/3276dfd8/attachment.bin>


Další informace o konferenci Hw-list