LPCxpresso: Potize s optimalizaci

Miroslav Šinko sinkomiro na gmail.com
Čtvrtek Červenec 28 00:19:33 CEST 2016


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-
>


Další informace o konferenci Hw-list