mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik AVR variablen gültigkeit & zugriff


Autor: Josh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo, ich habe ein kleines Problem mit dem angehängten code.

Ich möchte mithilfe der Funktion void displayDefRestTime() die 
rstTimeXxx variablen anzeigen, nachdem diese von der funktion restTime 
bearbeitet wurden.

Mein Problem ist, das mir der Compiler (AVR GCC) singemäß folgende 
Fehlermeldung ausgibt:
"variablen restTimeXxx in void restTime() nich declariert"

Welche möglichkeiten habe ich dies zu tun ohne globale oder statische 
Variablen einzusetzen? Eigendlich müssten doch meine variablen während 
des aufrufes von restTime() noch gültig sein, da die aufrufende Funktion 
nicht beendet wurde?
Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu 
geben?
Wie siehts mit Arrys oder pointern aus ?

//Resttime module
//it can be used with the RTC module


void displayDefRestTime()
{
  //define the variables for restTime()
  int rstTimeSek=userTimeSek;
  int rstTimeMin=userTimeMin;
  int rstTimeHour=userTimeHour;  

  //call Rest Time to process the rest Time
  restTime();

  //now we can display the rest Time
  lcd_write_int16(rstTimeHour);
  lcd_write_string(PSTR(":"));
    lcd_write_int16(rstTimeMin);
  lcd_write_string(PSTR(":"));
    lcd_write_int16(rstTimeSek);
  

  }//end of void displayRestTime()

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
void restTime()
{
  //don't forget to init the variables in the calling funktion.
  //the following ones are necesery
  
  for(int i=Sekunden;i>0;i--)
  {
  
    //looks if Sekonds are Zero
    if (rstTimeSek==NULL)
      {//if #0
     //..then looks if Minuten>0 and substracts one minute 
     //and set seconds to 60
     
     if(rstTimeMin) 
      { rstTimeMin--;
        rstTimeSek=60;}
        ////if minutes are Zero,
     else 
       { //else if#1
     //looks if Hour>0 and substracts one Hour 
     //and set Minutes to 60
         if(rstTimeHour)
      { rstTimeHour--;
        rstTimeMin=60;
           }//close else if#1 
          else
        rstTimeSek=0; //if rstTime Sek & Min & Hour is Zero, 
                    //let SEK Zero 
           }//#close else if#1
         }//close if#0
      else //Main If else, if Seconds not 0, substract 1 Second
        rstTimeSek--;

  }//end of while(Sekunde)




  for(int i=Minuten;i>0;i--)
  {
  
    //looks if Minutes are Zero
    if (rstTimeMin==NULL)
      {//if#0
        
    if(rstTimeHour)
    {//if#1
        rstTimeMin=60;
    rstTimeHour=NULL;       
        }//if#1
    else
    rstTimeMin=0; //if rstTime Min & Hour is Zero, let Min Zero 

         }//close if#0
      else //Main If else, if Seconds not 0, substract 1 Second
        rstTimeMin--;

  }//end of while(Minuten)


  for(int i=Stunden;i>0;i--)
  {
  
    //looks if rstTime hours aviable
    if (rstTimeHour)
      {//if#0

        rstTimeHour--;

     }//close if#0
   //if no Hours aviable let them Zero (do nothing)
  

  }//end of while(Stunden)



}//end of int restTime(); funktion

//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Danke
josh

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Josh schrieb:

> Mein Problem ist, das mir der Compiler (AVR GCC) singemäß folgende
> Fehlermeldung ausgibt:
> "variablen restTimeXxx in void restTime() nich declariert"
>
und recht hat er

> Welche möglichkeiten habe ich dies zu tun ohne globale oder statische
> Variablen einzusetzen?

keine

> Eigendlich müssten doch meine variablen während
> des aufrufes von restTime() noch gültig sein, da die aufrufende Funktion
> nicht beendet wurde?

nope.
In C wird der Scope von Variablen statisch zur Compiletime festgelegt. 
Wenn du dynamische Bindung willst, musst du dir einen LISP Dialekt 
suchen, der dynamische Bindung unterstützt.

> Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu
> geben?
> Wie siehts mit Arrys oder pointern aus ?

Wie wäre es, wenn du dir ein Einführungsbuch zu C zu Gemüte führen 
würdest? Dort erfährst du dann auch, dass man Funktionen Argumente 
mitgeben kann ....

int foo( int a, int b )
{
  return a + b;
}

int bar1()
{
  int h = 5, j = 8, m;
  int x = 10, y = 12, z;

  m = foo( h, j );
  z = foo( x, y );
}

... und das das der C-übliche Weg ist, wie die aufrufende Funktion der 
aufgerufenen Funktion einen Teil ihrer Variablen zur freundlichen 
Bearbeitung zur Verfügung stellt. Aber: Die aufrufende Funktion stellt 
der aufgerufenen Funktion Variablen zur Verfügung und nicht "die 
aufgerufene Funktion greift einfach auf Variablen des Aufrufers zu wie 
sie lustig ist"

Autor: Josh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen dank für die Antwort.

Ein solches buch habe ich mir zu gemüte geführt, und die funktionen 
deines Bsp sind mir bekannt.

ich hatte gehofft eine möglichkeit zu finden 3 variable zurück zu geben 
um die Funktion nicht 3fach ausführen zu müssen.

Aber wenn das nicht klappt werde ich diese eben umbauen müssen

mfg
josh

Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Deine Methode kann doch ein Array zurückgeben, in dem 3 Vars abgeleget 
werden.

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex G. schrieb:
> ein Array zurückgeben

auch das ist nicht einfach bzw sorgt für nette Effekte...

Lieber ein paar static Var. außerhalb deiner Fkt.

Autor: Filth __ (filth)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh ok, war mir so nicht bekannt.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannste ja referenzen in der Funktion übergeben, dann können die 
Parameter von der Funktion verändert werden.

void Increment(int &a)
{
  a++;
}


... //irgendwo im code

int i = 0;
increment(i);

//i ist jetzt 1

Autor: horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Eigendlich müssten doch meine variablen während des aufrufes von
> restTime() noch gültig sein, da die aufrufende Funktion
> nicht beendet wurde?

Die Funktion restTime kann ja auch von anderer Stelle aufgerufen werden. 
Z.b. von einer Funktion, in der es die entsprechenden Variablen nicht 
gibt.

> Gibt es auf uc eine möglichkeit mehrere variablen per return zurück zu
> geben?

Bei Arrays kannst du z.B. die Adresse übergeben. Ist ein wenig 
umständlich hier, vor allem wenn Du dich damit noch nicht so gut 
auskennst.

Nimm lieber Strukturen, dann hast du eine Variable mit mehrern Werten:

typedef struct
{
 int sek;
 int min;
 int hr;
} TIME;

TIME restTime (TIME rstTime)
{
 rstTime.sek = 1;
 rstTime.min = 2;
 rstTime.hr  = 3;

 return rstTime;
}

Autor: Josh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielen dank für die reichlichen Antworten.

>Bei Arrays kannst du z.B. die Adresse übergeben. Ist ein wenig
>umständlich hier, vor allem wenn Du dich damit noch nicht so gut
>auskennst.

Ich dachte zeiger sind aufgrund des adressbereiches bei AVRs 16 Bit 
lang, weswegen man vor der verwendung absehen sollte?

>Nimm lieber Strukturen, dann hast du eine Variable mit mehrern Werten:

Das kling gut, und werde ich in Zukunft wohl so machen.

Autor: Bernd O. (bitshifter)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo schrieb:
> void Increment(int &a)
> {
>   a++;
> }
>
> int i = 0;
> increment(i);
>
> //i ist jetzt 1
Nicht ganz. Erst mal müssen die Fehler beseitigt werden ;-)

1:
> void Increment(int &a)
> {
>   a++;
> }
a ist eine Adresse und kein Wert. Der Inkrement wirkt aber auf die 
Adresse. Korrekt wäre:
(*a)++;

2:
Der Compiler kennt nun die Funktion "Increment", aufgerufen wird aber 
"increment" (case-sensitive).

3,
Die Funktion erwartet einen Pointer auf int, bekommt aber ein int.
Korrekt wäre:
"Increment(&a);"


Gruß,
Bernd

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd O. schrieb:

> 1:
>> void Increment(int &a)
>> {
>>   a++;
>> }
> a ist eine Adresse und kein Wert.

Hier wird eine Referenz erwartet, kein Zeiger. Das ist so richtig.

> Die Funktion erwartet einen Pointer auf int, bekommt aber ein int.
> Korrekt wäre:
> "Increment(&a);"

Nein, siehe oben.

Autor: horst (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich dachte zeiger sind aufgrund des adressbereiches bei AVRs 16 Bit
> lang, weswegen man vor der verwendung absehen sollte?

Und wie lang sind drei int? Die werden bei meiner Variante nämlich 
lustig auf dem Stack herumkopiert. Diese Variante ist auch nicht auf 
Effizienz ausgelegt.

Wenn ich mich recht erinnere, ist ein int auch 16 Bit lang. int8_t oder 
uint8_t reichen hier aber evtl. auch.

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Stegemann schrieb:
> Bernd O. schrieb:
>
>> 1:
>>> void Increment(int &a)
>>> {
>>>   a++;
>>> }
>> a ist eine Adresse und kein Wert.
>
> Hier wird eine Referenz erwartet, kein Zeiger. Das ist so richtig.

Moment, reden wir hier von C oder von C++?

Autor: Hc Zimmerer (mizch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt einen Weg, die ursprüngliche Absicht umzusetzen, aber nur mit 
gcc.  gcc kann nested functions (eine Funktionsdefinition innerhalb 
einer anderen).  Diese innerhalb definierte Funktion kann auf die 
lokalen Variablen der Funktion(en), in denen sie steht, zugreifen.

Also genau das, was der TE ursprünglich wollte.  Man muss sich nur klar 
sein, dass das kompatibel zu nix außer der gcc-Familie ist.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also ich hab den Code vor dem Posten kurz im devcpp ausprobiert 
(natürlich mit nem großen 'I' beim Aufruf) und es funktioniert so.

Das ganze nennt sich Referenz und so könnte der TE einige Werte, die er 
als Parameter verwendet, durch die Funktion verändern lassen.
So hab ich die Frage wenigstens verstanden.
:-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Flo schrieb:
> Also ich hab den Code vor dem Posten kurz im devcpp ausprobiert
> (natürlich mit nem großen 'I' beim Aufruf) und es funktioniert so.

Du hast einen C++ Compiler benutzt.
In C gibt es keine Referenzen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.