Strana 1 z 1

Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 11:56
od používateľa romiadam
Ahojte,
Viem ze ak pred main() deklarujem premennu, tak je to globalna premenna.
A ked premennu deklarujem vo vnutri nejakej funkcie tak je lokalna premenna pre tu funkciu a ona "umrie" akonahle program opusti tu funkciu kde bola deklarovana.

Otazka1: Tato lokalna premenna c (vid priklad nizsie)deklarovana vo funkcii Vypocet(), je platna aj v dalsich volanych funkciach?
(Pozn. Nehladajte v tom logiku, je to len ilustracia co mam na mysli.)

Kód: Vybrať všetko

int a;
int b;
int vysledok;
main()
{
vysledok = Vypocet();
}

int Vypocet()
{
int c;
int d;
c=a+b	// a, b, su glob. premenne - zname
d = Delenie();
return (c+d);
}

int Delenie()
{
return=c/2;		// c je lokalna prenmenna deklarovana vo Vypocet(). Je znama aj tu? 
				//Popr. ak by sa zavolala dalsia funkcia, je znama aj tam?
}

Bez ohladu na to ci sa to robi takto alebo nie (toto je len priklad ci chapem lok. premennu), fungoval by ten priklad?



Otazka 2:
Mozem aj takto vytvorit blok a v nom lokalnu premennu len pre konkretny vypocet? Potrebujem "podrzat" na chvilku privypoctoch nejaky medzi vysledok
(Pozn. Nehladajte v tom logiku, je to len ilustracia co mam na mysli.)

Kód: Vybrať všetko

int  a;
main()
{
	prikaz;
	prikaz;
		{
		int c;
		c= a/3;
		a= c+5;
		}
	prikaz;
	prikaz;	
}
Toto vyssie by fungovalo alebo nie?

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 12:07
od používateľa maskrtnik01
Otázka 1: Premenná deklarovaná v rámci nejakej funkcie je platná iba v danej funkcii. Ak chcete jej hodnotu použiť v ďalšej funkcii, je možné ju predať ako parameter. Ak ju chcete vnútri volanej funkcie zmeniť tak, aby sa zmena prejavila vo volajúcej funkcii, je možné predať pointer na premennú ako parameter.

Otázka 2: Tak o tomto som vôbec nevedel. Takúto deklaráciu premennej som v živote nepoužil, ale skutočne je možné deklarovať premennú v bloku kódu, a mimo tento blok nebude platná. V ďalšom bloku môže byť deklarovaná premenná s rovnakým názvom.

Moja otázka: Syntakticky je deklarácia z otázky 2 možná a bude fungovať. Avšak z hľadiska prehľadnosti, je toto prínosom, alebo naopak?

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 12:41
od používateľa Atlan
Premena c takto fungovat nebude a kedy si to hodil to prekadaca vyhodi chybu. Lebo v f7nkcii delenie nieje deklarovana

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 15:36
od používateľa romiadam
Aha, takze napriek tomu ze c je deklarovane vo Vypocet() a Delenie() je volane z Vypocet(), to neznamena ze c bude existovat aj v Delenie() .
Zaujimave. Ja som si myslel ze bude existovat vo vsetkych volanych funkciach.


A co ten blok? (Otazka 2). To by mohlo tak byt?

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 15:44
od používateľa maskrtnik01
Nikdy som to nepoužil, myslím že je to aj neprehľadné. Ale overil som si to, dá sa to.

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 15:46
od používateľa Andy99
Otazka 2: Bud to fungovat, syntakticky je to spravne, ale neodporucal by som toto riesenie. (Mozes si tym narobit viac problemov, ako osohu.) Skor sa to pouziva s blokom with, ktory, ale nie je v C k dispozicii.

Mozno som nepochopil kontext, ale pokial chces setrit pamat a pouzivat lokalne premenne v inych funkciach, sluzia to pointre a referencie ako parametre funkcie.

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 19:54
od používateľa peterple
Už to tu bolo viac menej zopovedané. K bodu dva len malé doplnenie. Samozrejme že sa to používa. Že sa to niekomu javí ako neprehľadné je jeho vec.

Úplne bežne sa to používa napríklad aj takto

Kód: Vybrať všetko

  int i= 10;

	for (int i=0; i<100; i++)
	{
		 printf("%d\n", i);
	}
Premená i v cykle sa vytvorí nová lokálna a zatieni aj tú predtým vytvorenú premennú (lokálnu či globálnu). Teda v cykle mi ide i od jedna po sto. Ale ked cyklus skončí tá vnútorná premenná i zanikne a tá nad tým i sa znova objaví a bude mať hodnotu 10.

C je prechádzka mínovým poľom a kto nie je pyrotechnik si ľahko na nejakú tú mínu nabehne.

Na podobné pokusy je dobré si nainštaľovať C na PC s poriadnym IDE kde je aj solidny debuuger a potom krokovať sa sledovať ako to všetko funguje, krok za krokom.
Pre jednočipy sa dá použiť simulátor.

Re: Lokalna premenna - ujasnenie

Napísané: 26 Sep 2022, 23:28
od používateľa balu
peterple napísal:Úplne bežne sa to používa napríklad aj takto


Kód: Vybrať všetko

 int i= 10;

	for (int i=0; i<100; i++)
	{
		 printf("%d\n", i);
	}
Použít to takhle jde, ale běžně se to přímo takhle nepoužívá (tedy myslím definování stejných proměnných v rámci jedné funkce) - ztrácíš tak přehled.

Toto se skutečně používá :

Kód: Vybrať všetko

	for (int i=0; i<100; i++)
	{
		 printf("%d\n", i);
	}
I když místo proměnné i se používá (třeba) Idx. Celé to pak vypadá takto :

Kód: Vybrať všetko

	for (int Idx=0; Idx<100; Idx++)
	{
		 printf("%d\n", Idx);
	}

Použití jednopísmenných (nebo obecně krátkých) proměnných je dobré se vyhybat, stejně tak jako je dobré se vyhybat proměnným s nic neříkajícím názvem (pomocna1, pomocna2, ... pomocna9 atd.). Cčko rozlišuje malá a velká písmena, takže tahle_promenna není Tahle_promenna. Tohle je věc, kterou v žádném případě nedělej - používat dvě různé proměnné rozlišené jenom velikostí písmen.

Je rozdíl mít proměnné s názvem DP, PP nebo DelkaPulzu, PocetPulzu. Proměnné, konstanty atd. by měly dávat smysl. To jediné přispívá k přehlednosti kódu. A když pak dodržuješ formát názvů, tak na první pohled do programu vidíš, jestli jde o lokální/globální proměnnou, IO pin nebo konstantu.

Stejně tak je dobré vyhybat se psaní čísel, týkajících se třeba rozměrů polí (ale třeba i nějakých konstant apod.) přímo do kódu. Takže místo deklarace a použití pole takto :

Kód: Vybrať všetko

int PolePrvku[10];

void NastavPole( void )
{
    for ( int Idx = 0 ; Idx < 10 ; Idx++ )
    {
        PolePrvku[Idx] = 10;
    }
}
je mnohem lepší místo čísla 10 použít definovanou konstantu :

Kód: Vybrať všetko

#define POCET_PRVKU 10
int PolePrvku[POCET_PRVKU];

void NastavPole( void )
{
    for ( int Idx = 0 ; Idx < POCET_PRVKU ; Idx++ )
    {
        PolePrvku[Idx] = 10;
    }
}
ideálně pak :

Kód: Vybrať všetko

#define POCET_PRVKU 10
#define VYCHOZI_HODNOTA 10
int PolePrvku[POCET_PRVKU];

void NastavPole( void )
{
    for ( int Idx = 0 ; Idx < POCET_PRVKU ; Idx++ )
    {
        PolePrvku[Idx] = VYCHOZI_HODNOTA;
    }
}
Tím se pro změnu vyvaruješ chyb, když pak chceš změnit rozměr pole tím, že :
  1. Nespleteš si dvě stejná čísla, která v programu mají různý význam (která 10 je ta správná ?)
  2. Na žádné místo, které potřebuješ změnit nezapomeneš
Ale vraťme se k lokálním/globálním proměnným.

Lokální proměnná (obecně) je proměnná, která je nadefinovaná mezi složenými závorkami { } a je jedno, jestli unvnitř cyklu, funkce nebo bloku.

Pokud potřebuješ, aby lokální proměnná v nějaké funkci byla k dispozici pouze této funkci, ale neztrácela svou hodnotu, může tak být nadeklarována. Například použití jako čítače nebo pro rozfázování nějakého procesu.. Taková proměnná se pak deklaruje jako lokální (tedy uvnitř funkce), ale s příznakem "static" :

Kód: Vybrať všetko

void BlikejLedkou( void )
{
  static int _Krok = 0;

  switch ( _Krok )
  {
    case 1: LedZelenaOut = SVITI;       // Rozsvítit LED
            LedTimer = T_500MS;         // Nastavit časovač na 500ms
            _Krok++;                    // Do dalšího kroku
            break;

    case 2: if ( !LedTimer ) _Krok++;   // Pokud časovač dopočítal, jdi do dalšího kroku
            break;

    case 3: LedZelenaOut = NESVITI;     // Zhasnout LED
            LedTimer = T_500MS;         // Nastavit časovač na 500ms
            _Krok++;                    // Do dalšího kroku
            break;

    case 4: if ( !LedTimer ) _Krok = 1; // Pokud časovač dopočítal, jdi do prvního kroku
            break;

    default: _Krok=1;  // Tohle snad vysvětlovat nemusím ...
             break;
  }
}

Poznámka :
_Krok - lokální proměnná
LedZelenaOut - je to proměnná, která označuje IO pin, kde je zelená LEDka připojená (to znamená to Out na konci)
LedTimer - globální proměnná
SVITI, NESVITI, T_500MS - nadefinované konstanty

Lokální proměnná s příznakem "static" se chová jako lokální, ale má trvale přidělenou paměť stejně, jakoby to byla globální proměnná.

Re: Lokalna premenna - ujasnenie

Napísané: 27 Sep 2022, 12:06
od používateľa romiadam
Dakujem pekne za odpovede. Vidim, ze sa to vysvetlilo viac nez bolo treba. Teraz to uz chapem. :thumbup:
Dakujem.