www.mikrocontroller.net

Forum: Compiler & IDEs Falscher Parameter bei Übergabe an Funktion


Autor: Slowflyer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich habe eine Funktion zur Berechnung von Wochentag geschrieben:
int8_t dayofweek(int8_t tag, int8_t monat, int8_t jahr){...}

Wenn ich diese zum Testen folgendermaßen aufrufe:
var = dayofweek(1,3,5); // 01.03.2005

gibt es Probleme. Im AVR-Stduio wird bei der Simulation der zweite
Parameter nicht korrekt übergeben. Der erste Parameter wird in Register
24, der zweite in r25 und der dritte in r20 übergeben. Der Tag und das
Jahr sind korrekt, der Monat steht aber in r22 und nicht in r25.

Ich verwende den avr-gcc 3.4.4, avr-libc 1.2.5. , die Optimierung -O1
und das AVRStudio 4.12 Build 456 (sonst bekomme ich die Software nicht
mehr in den µC).

Meine Frage nun, ist das ein Bug (Compiler, Studio etc.) oder habe ich
etwas übersehen?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bitte poste einen Beispielcode.

Autor: Slowflyer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier ein Beispielcode. Hab das mal aus dem Projekt ausgekoppelt und für
den Mega88 kompilert mit den Optimierung -O1. Das Ergebnis ist wie oben
beschrieben.
#include <io.h>

int8_t dayofweek(int8_t tag, int8_t monat,int8_t jahr) 
{
  static int8_t tage[] = {0,3,3,6,8,11,13,16,19,21,24,26,29};

  

  int8_t schaltjahr = 0;
  int tage_im_jahr;
  int8_t wochentag;

  tage_im_jahr = tag;
  tage_im_jahr += tage[monat-1];
  tage_im_jahr += schaltjahr;
  wochentag = tage_im_jahr%7;
  wochentag += 5; // Doomday 1.1.05 = Samstag
  wochentag %= 7;
  
  return wochentag;
}

int8_t main()
{
  int8_t var;
  var = dayofweek(1,3,5);
  var = var-10;
  return var;
}
  
  

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der generierte Code sieht OK aus.  tag, monat und jahr werden in
r24, r22 und r20 übergeben.  Da jahr nicht ausgewertet wird, wird
der Inhalt von r20 ignoriert, r22 und r24 werden ordnungsgemäß
in interne Register kopiert:

        mov r18,r24
        clr r19
        sbrc r18,7
        com r19

und später von dort benutzt.  Da du sie als int8_t deklariert
hast, wird eine sign extension vorgenommen.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin, ich krame mal den Thread heraus, weil ich ein ähnliches Problem
habe.
Ich habe eine Funktion mit den Parametern a,b,c. Rufe ich diese
Funktion auf, werden die Parameter vertauscht - aber nur, wenn ich als
Funktionsparameter das Ergebnis einer anderen Funktion übergebe.
Ich nutze die relativ alte Version 20040720 des Winavr - ist dieser
Fehler durch die Version bedingt und bei einer aktuelleren Version
behoben? Oder mache ich irgendetwas falsch?


test (get_digit(),get_digit(),get_digit());

Gebe ich nun "1", "2", "3" ein, bekomme ich als Ausgabe "3",
"2", "1" - Also genau verdreht.

RS232_wait() wartet auf ein Zeichen von der seriellen Schnittstelle und
gibt es zurück
RS232_send() sendet ein Zeichen
RS232_text() sendet eine Zeichenkette

[code]

uint16_t get_digit (void)
{
  uint8_t text[10];
  uint8_t *pointer;
  uint8_t zeichen;

  pointer = text;

  do
  {
    zeichen = RS232_wait();
    *pointer++ = zeichen;
  }
  while (zeichen != 0x0D);
        *pointer = 0x00;

  return atoi (text);
}

void test (uint16_t a, uint16_t b, uint16_t c)
{
  uint8_t text[10];

  itoa (a,text,10);
  RS232_text(text);
  RS232_send (0x0D);

  itoa (b,text,10);
  RS232_text(text);
  RS232_send (0x0D);

  itoa (c,text,10);
  RS232_text(text);
  RS232_send (0x0D);
}
[\code]

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

Bewertung
0 lesenswert
nicht lesenswert
> ist dieser
> Fehler durch die Version bedingt und bei einer aktuelleren Version
> behoben? Oder mache ich irgendetwas falsch?
>
>
> test (get_digit(),get_digit(),get_digit());
>
> Gebe ich nun "1", "2", "3" ein, bekomme ich als Ausgabe "3",
> "2", "1" - Also genau verdreht.

Was dieser Code genau macht ist undefiniert.
In C ist die Reihenfolge, in der Argumente ausgewertet
werden nicht definiert.
Du koenntest also  "3", "2", "1" kriegen, oder "2", "1",
"3"
oder "1", "3", "2" oder ....

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die schnelle Antwort, das bringt Licht in die Sache. Ich habe
so etwas ja schon fast vermutet, wäre nicht das erste Mal, dass C
anders reagiert, als ich dachte.
Warum kann C nicht einfach logisch sein und die Parameterliste von
links nach rechts durcharbeiten :(
Wieder einer der Tage, an denen ich die Entscheidung, C zu
programmieren, in Frage stelle ;)

Wieder etwas dazugelernt.
Danke!

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

Bewertung
0 lesenswert
nicht lesenswert
> Warum kann C nicht einfach logisch sein und die Parameterliste von
> links nach rechts durcharbeiten :(

Weil C als Praemisse hat: Jeder Compilerbauer soll
das Optimium aus der Zielmaschine herausholen koennen.
Und auf den meisten Stack-basierten CPU's ist es nun
mal so, dass die Argumentuebergabe am Stack am schnellsten
geht, wenn man die Argumentliste von rechts nach links
abarbeitet. :-)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wieder einer der Tage, an denen ich die Entscheidung, C zu
> programmieren, in Frage stelle ;)

Warum?  Du kannst doch die Werte allemal in einer Variablen
zwischenspeichern.  Was anderes müsste der Compiler ja auch nicht tun,
wenn er gemäß deiner Logik funktionieren würde -- nur dann müsste er
stets eine solche belegen, während es ihm eben so freigestellt ist,
die effektivste Variante zu suchen.  In den allermeisten Fällen
interessiert einen nämlich die Reihenfolge, in der die Seiteneffekte
für die aktuellen Funktionsparameter evaluiert werden, eher nicht.

Alternativ: lass deine get_digit()-Funktion an Hand eines Parameters
entscheiden, welches Digit sie zurückgeben soll, dann kannst du mit

test (get_digit(1),get_digit(2),get_digit(3));

eine exakte Vorgabe erzielen.

Autor: thkais (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jörg: Warum? Weil es solche Fußangeln sind, die einem das Leben schwer
machen. Bei Assembler konnte ich zu 100% davon ausgehen, dass ich
selber Mist gebaut habe, wenn etwas nicht funktionierte. Jetzt muss ich
mit Fehlern leben, bei denen ich nicht sofort die Ursache erkenne... Das
ist m.E. nicht im Sinne eines Programmierers. Aber ich bin nicht
allein:

http://www.math.uni-bremen.de/~thielema/CHater.html

(Aber den Zwinkermann ;) hast Du schon gesehen, gelle?)

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nun, deine URL deutet aber eher darauf hin, dass die Leute
dahinter nach einer höheren Programmiersprache (insbesondere
eine mit automatischer Verwaltung der Objekte) rufen, nicht
nach einer, bei der die Möglichkeit für Fehler ein bis zwei
Größenordnungen mehr sind...

Aber generell: bei einer höheren Programmiersprachen in
irgendeiner Form musst du dich halt mit deren Definition
vertraut machen.  Ada ist sicher auch 'ne gute Alternative,
sieht nicht ganz so kryptisch aus wie C.  Hab's selbst noch
nicht gemacht.

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.