Variables ve funkcích

Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
x-f
Příspěvky: 3
Registrován: 19 zář 2019, 11:01
Reputation: 0

Variables ve funkcích

Příspěvek od x-f » 19 zář 2019, 11:28

Ahoj.

Jsem tu nový, tak na mě budtě hodní. ;)
Mám dotaz, který jsem úplně nevygooglil.

Mám definované nějaké proměnné. Vše mám definované v hlavním programu. Proměnné ve funcích definované nemám, ale pro přehlednost funkce používám.

Jak se to má s přenosem proměnných mezi loopem a funkcí, funkcí a loopem a mezi funkcí a funkcí? Dočetl jsem se, že proměnná ve funkci se dá použít jen v dané funci, ale co když ve funkci používám proměnou definovanou globálně?

Narazil jsem totiž na to, že se některé globální promměné ve funci použít dají a jiné ne a nechápu proč jsou tam ty rodíly.

Například mám několik proměnných s hodnotou. Pak mám funkci "void writeSD()", kterou zavolám "writeSD();"
Uvnitř funkce zapisuji asi tak 10 proměnných na SD. 6 se mě jich zapíše a zbylé 4 mají hodotu 0, ačkoliv v hlavní smyčce loop hodnotu mají. Přitom všechny jsou definované globálně. Nevypozoroval jsem, že by to souviselo s typem té promměné, nebo s tím, zda proměnná dostala hodnotu v loopu, nebo v jiné funkci.

Když si to upravím a promměné vydefinuji při volání funkce např. "writeSD(alt, altKalman, mainFire);" a ve funkci např. "void writeSD(float alt, float altKalman, bool mainFire)" tak už se mě tam hodnota proměnné přenese. Nechápu ale, proč to u některých proměnných funguje i bez.

Principielně bych uvítal, kdyby ty globální proměnné byli vidět prostě všude skrze loop i všechny funkce, ale to nevím zda jde (ačkoliv bych řekl, že některé z těch proměných se tak chovají).



Dále jsem narazil na ještě jedno divné chování, které nevím zda souvisí.

Mám globální proměnnou float, která nabývá v loopu hodnotu příkazem z knihovny.
Konkrétně: float altKalman = pressureKalmanFilter.updateEstimate(alt);

Hned pod tím mám v loopu:
prevAltKalman = altKalman;

Když si následně vypíši obě promměné, tak altKalman má nějakou hodnotu a prevAltKalman má stále hodnotu 0. Nechápu kde je chyba. Obě jsou float, vše se odehrává v loopu.

Přitom hned pod tím mám toto a tam se mě hodota přenese.
if (altKalman > maxAltKalman) {
maxAltKalman = altKalman;
}



Díky.

x-f
Příspěvky: 3
Registrován: 19 zář 2019, 11:01
Reputation: 0

Re: Variables ve funkcích

Příspěvek od x-f » 19 zář 2019, 12:43

Možná si odpovím sám na druhou část.

Když mám definouvanou globální proměnnou:
float altKalman;

a pak v loopu:
float altKalman = pressureKalmanFilter.updateEstimate(alt);

Tak to je nově definovaná promměná ke které není z vnitřku funkcí přístup?
Je zajímavé, že v loopu samotném pak zřejmě náhodně dochází někdy k použití té globální a někdy té druhé.

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Variables ve funkcích

Příspěvek od pavel1tu » 19 zář 2019, 12:48

Dej sem celý zdroják pomocí "zobrazení kodu"
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

ArduXPP
Příspěvky: 361
Registrován: 14 pro 2017, 19:31
Reputation: 0
Kontaktovat uživatele:

Re: Variables ve funkcích

Příspěvek od ArduXPP » 19 zář 2019, 13:35

Když máš stejný název, tak do bude dělat, ale když dáš do loop1 a loop2 stejný název, tak to nebude vadit.

Uživatelský avatar
pavel1tu
Příspěvky: 2054
Registrován: 26 říj 2017, 08:28
Reputation: 0
Bydliště: Trutnov
Kontaktovat uživatele:

Re: Variables ve funkcích

Příspěvek od pavel1tu » 19 zář 2019, 13:49

Testnul jsem to,

ne tedy se zápisem na SD,
ale třeba zápisem do EEPROM,
odeslání po 485,
odeslání na WEB.

Já dělám skoro vše funkcemi, ty pak využívám i v jiných projektech,
vždy definuji proměnné globálně,
nikdy mi to neudělalo co zmiňuješ.

Nedělá to knihovna k SD kartě ?
Nedělají to jen proměnné nějakého typu ?
Nemají ty proměnné název který koliduje s nějakou knihovnou nebo něčím ? (já proto proměnné pojmenovávám "cecky", tedy jako česky)

Musí v tom být logika přeci .... podle čeho to kompilátor zkompiluje a poté to nefunguje.
UNO, NANO, Mikro, PRO mini, DUE, ESP32S2, RPi PICO
Pavel1TU
"Správně napsaný kod lze číst jako knihu"

x-f
Příspěvky: 3
Registrován: 19 zář 2019, 11:01
Reputation: 0

Re: Variables ve funkcích

Příspěvek od x-f » 19 zář 2019, 16:08

Klucí testnu to večer doma. Teď nemám u sebe.

Zatím mám pracovní teorii, že jsem tímto nadefinoval jednu globální proměnou a druhou v loopu stejného názvu. Přičemž funkce si šáhne na tu globální a i v loopu se to chovalo divně. Udělal jsem si teď jen test v simulátoru a chová se to přesně tak.

Kód: Vybrat vše

float test=0;

void setup() {
Serial.begin(9600);

void loop() {

Serial.println(test);
Serial.println("Test z loopu");

delay(1000);

float test=1;

Serial.println(test);
Serial.println("Test z loopu");

delay(1000);

funkce();

}

void funkce() {
Serial.print(test);
Serial.println("Test z funkce");
delay(1000);
}

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Variables ve funkcích

Příspěvek od kiRRow » 19 zář 2019, 16:28

Je potřeba si uvědomit, že loop a setup jsou taky funkce. Pokud v nich deklaruješ proměnnou, bude dostupná pouze v rámci oné funkce.

Kód: Vybrat vše

int a = 1; // tato proměnná je globální a bude dostupná z jakékoliv funkce

void setup() {
	int b = 1; // tato proměnná je lokální a bude dostupná pouze v rámci setup
	Serial.begin(9600);
}

void loop() {
	ínt c = 1 // tato proměnná je lokální a bude dostupná pouze v rámci loop

	Serial.println(a); // dostaneš 1 (je to globální proměnná)
	Serial.println(b); // dostaneš 0 (protože v této funkci není proměnná b definována)
	Serial.println(c); // dostaneš 1 (lokální proměnná dostupný v loopu)
	
	vypisABC();
}

void vypisABC(){
	Serial.println(a); // dostaneš 1 (je to globální proměnná)
	Serial.println(b); // dostaneš 0 (protože v této funkci není proměnná b definována)
	Serial.println(c); // dostaneš 0 (protože v této funkci není proměnná c definována)
}

Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Variables ve funkcích

Příspěvek od gilhad » 19 zář 2019, 16:36

Je to celkem jednoduche:
  • promenna definovana uvnitr funkce (scopu) je viditelna jen uvnitr funkce scopu), po skonceni funkce scopu) zanika, pri zavolani funkce (scopu)je zalozena nova.
  • promenna definovana globalne je viditelna globalne, vznika pri startu programu, zanika pri jeho ukonceni (u arduina tedy nikdy)
  • promenna definovana uvnitr funkce prekryje promennou definovanou globalne (tedy pri pouziti toho jmena se mysli promenna z nejblizsi oblasti (funkce)
zajimave dopady:
  • setup() i loop() jsou funkce, takze to na ne plati taky
  • slozene zavorky a cykly jsou scoop, takze to na ne plati taky
priklad

Kód: Vybrat vše


int glob; //globalni promenna
int i=1; //globalni i
nastav (){
  int loc; // lokalni v nastav
  loc=i; // priradim hodnotu globalniho i, tedy 1
  glob=loc; // loc lokalni v nastav, nastavene na 1 z globalniho i
}
setup(){
  int loc; // lokalni v setupu - nijak nesouvisi s s loc z nastav, a naopak
  int i=2; //lokalni v setup, nesouvisi s globalnim i
  loc=i; // pouziju lokalni i, tedy 2
  for (int i=10;i<=20;i++) { // lokalni ve for, nesouvisi ani s globalnim i, ani s i lokalnim v setupu
  	loc=i; // prirazuju i z for ..., tedy 10..20
  	{
  	   int i=40; //lokalni v techto zazvorkach
  	   loc=i; // loc lokalni v setup, i lokalni v zavorkach, priradim 40, vzdy
  	   nastav(); // v nastav se do jeho lokalni loc nastavi globalni i, tedy 1
  	   // glob je nastavene na 1
  	   glob=loc; // tady se pouzije loc lokalni v setupu, do ktere je prirazena 40 z i lokalniho v techto zavorkach
  	 };
        glob=loc; // tady se pouzije loc lokalni v setupu, do ktere je prirazena 40 z i v zavorkach, ktere ale uz neni
  	loc=i; // prirazuju i z for ..., tedy 10..20  	 
        glob=loc; // tady se pouzije loc lokalni v setupu, do ktere je prirazena 10..20 z i lokalniho ve for
   }; /// konec for
  loc=i; // pouziju lokalni i, tedy 2
  glob=loc; // tady se pouzije loc lokalni v setupu, do ktere je prirazena 2 z i lokalniho v setupu
  pinMode(10,INPUT); //pin 10 je pro cteni
}

loop(){
 int loc; //lokalni v loop
 int i=99; // lokalni v loop
 Serial.print(glob); // glob je v prvnim pruchodu nastavene ze setup na 2, v dalsich pruchodech na je 0 nebo 1, podle tlacitka v minulem pruchodu
 loc=i; // lokalni i  v loop je 99
 nastav(); // glob nastavi na 1 (z globalniho i)
 Serial.print(glob); // glob je nastavene na 1 z nastav()
 glob=loc; // nastavene z lokalniho loc, nastaveneho z lokalniho i na 99
 Serial.print(glob); // glob je nastavene na 99
 glob=digitalRead(10); // bud 1, nebo 0 podle tlacitka
 Serial.print(glob); // glob je nastavene na 0 nebo 1podle tlacitka pred chvili v tomto pruchodu
}



Uživatelský avatar
gilhad
Příspěvky: 778
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Variables ve funkcích

Příspěvek od gilhad » 19 zář 2019, 16:39

kiRRow píše:
19 zář 2019, 16:28
Je potřeba si uvědomit, že loop a setup jsou taky funkce. Pokud v nich deklaruješ proměnnou, bude dostupná pouze v rámci oné funkce.

Kód: Vybrat vše

void loop() {
	ínt c = 1 // tato proměnná je lokální a bude dostupná pouze v rámci loop

	Serial.println(a); // dostaneš 1 (je to globální proměnná)
	Serial.println(b); // dostaneš 0 (protože v této funkci není proměnná b definována)
IMHO dostanes chybu prekladace (neznama prommenna b), protoze promenna b NENI dostupna v tomto miste, obdobne v dalsi funkci b a c

Uživatelský avatar
kiRRow
Příspěvky: 1151
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Variables ve funkcích

Příspěvek od kiRRow » 19 zář 2019, 16:45

gilhad píše:
19 zář 2019, 16:39
kiRRow píše:
19 zář 2019, 16:28
Je potřeba si uvědomit, že loop a setup jsou taky funkce. Pokud v nich deklaruješ proměnnou, bude dostupná pouze v rámci oné funkce.

Kód: Vybrat vše

void loop() {
	ínt c = 1 // tato proměnná je lokální a bude dostupná pouze v rámci loop

	Serial.println(a); // dostaneš 1 (je to globální proměnná)
	Serial.println(b); // dostaneš 0 (protože v této funkci není proměnná b definována)
IMHO dostanes chybu prekladace (neznama prommenna b), protoze promenna b NENI dostupna v tomto miste, obdobne v dalsi funkci b a c
První chybu dostaneš hned za loopem, protože mi tam chybí středník :D

Neslouží to ke kompilaci, ale jen k ukázce toho jak se chovají ty proměnné.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 9 hostů