Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 25

Thema: printf nimmt immer das erste argument

  1. #1
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79

    Question printf nimmt immer das erste argument

    Hallo!
    Wie arbeitet printf denn die liste der argumente ab? bei follgedem code wird zwei mal das erste agrument genommen, obwohl zwei verschiedene angegeben sind:

    printf("now: %s last access: %s", ctime(&t_now), ctime(&t_file));
    Gibt beide male dasselbe datum aus (t_now), die beiden daten unterschiedlich sind!!!
    Wenn man aber die ausgabe auf zwei zeilen verteilt:

    printf("now: %s", ctime(&t_now));
    printf("last access: %s", ctime(&t_file));

    ist alles wieder in ordnung (es werden zwei unterschiedliche daten ausgegeben)!

    Hier nochmal das ganze programm:
    Code:
    #include <stdio.h>
    #include <time.h>
    #include <sys/stat.h>
    
    int main() {
    int stat_retval;
    char *sf_name = "sayhello.c";
    struct stat sf_stat;
    time_t t_now, t_file;
    
    stat_retval = stat(sf_name, &sf_stat);
    t_file = sf_stat.st_atime;
    t_now = time(NULL);
    
    printf("Now: %s last access: %s", ctime(&t_now), ctime(&t_file));
    printf("now: %s", ctime(&t_now));
    printf("last access: %s", ctime(&t_file));
    return(0);
    }

  2. #2
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Ich habs! Es liegt an ctime()! Das ergebnis des zweiten aufruffs wird einfach überschrieben(C arbeitet die funktions-parameter doch von rechts nach links oder?). es heißt nähmlich im manual:
    "The return value points to a statically allocated string which might be overwritten by subsequent calls to any of the date and time functions."
    Geändert von TrollSlayer (09-09-2003 um 15:17 Uhr)

  3. #3
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von TrollSlayer
    Ich habs! Es liegt an ctime()! Das ergebnis des zweiten aufruffs wird einfach überschrieben(C arbeitet die funktions-parameter doch von rechts nach links oder?).
    Nein,die Reihenfolge der Abarbeitung ist undefiniert bei Funktionsargumenten.
    Es gibt keinen Sequenzpunkt,der nächste ist erst wieder beim ;

    Das Problem mit der statischen Variablen hast du ja selber gelöst .

  4. #4
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Doch es gibt sicher eine bestimmte reihenfolge bei der funktionsparameter-abarbeitung. Bei c war das glaube ich von rechts nach links und bei pascal umgekehrt.

  5. #5
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Sorry! habe mich vielleicht falsch ausgedrückt. nicht abarbeitung sondern die reihenfolge der übergabe an die funktion.

  6. #6
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von TrollSlayer
    Sorry! habe mich vielleicht falsch ausgedrückt. nicht abarbeitung sondern die reihenfolge der übergabe an die funktion.
    Nein,es ist so wie ich sage.Trust me ^^.

    Test Code
    Code:
    #include <stdio.h>
    
    int n;
    int f(int (*g)());
    int f(int (*g)())
    {
       int m;
       m = n;
       if(m == 0)
          return 1;
       else
       {
          n--;
          return m * g(g);
       }
    }
    
    int main()
    {
       n = 5;
       printf("%d %d\n",n,f(f));
       n = 5;
       printf("%d %d\n",f(f),n);
       return 0;
    }
    überlege dir was rauskommt,und dann lass es laufen.

    Die Abarbeitung von links nach rechts gibt es bei || und &&,und beim Kommaoperator (das , beim Funktionsaufruf ist kein Kommaoperator)

  7. #7
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    ok. das sieht überzeugend aus. aber im "Assembler Buch" 3. Auflage steht follgendes:
    "Offensichtlich arbeitet sich also der Compiler vor rechts nach links durch die Parameter, also genau anders herum als Pascal. C arbeitet die Parameter, die Routinen übergeben werden, von rechts nach links ab."

  8. #8
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Nein! Das stimmt schon mit der reihenfolge: von rechts nach links)! Schau die den assembler code den gcc aus deinem programm generiert:
    beim ersten printf:
    die funktion f wird zuerst ausgeführt, dann das ergebnis davon auf den stack gelegt, dann das n.
    beim zweiten printf:
    es wird wieder zuerst f ausgeführt, dann jedoch das n auf den stack gelegt und dann erst der rückgabewert von f!

  9. #9
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von TrollSlayer

    "Offensichtlich arbeitet sich also der Compiler vor rechts nach links durch die Parameter, also genau anders herum als Pascal. C arbeitet die Parameter, die Routinen übergeben werden, von rechts nach links ab."
    Ja,der Grund,daß das dort so steht ist der,daß früher (also in der IT-Steinzeit),Funktionparameter auf den Stack gepusht wurden.
    Pascal machte das von links nach rechts,und C von rechts nach links.
    C macht das von rechts nach links,damit bei Funktionsaufrufen mit Variablerargumentenliste (zb. printf),der Formatstring ganz oben auf dem Stack lag.

    So,aber erstens werden heutezutage (die Rechner haben heute viele Register),die meisten Parameter in Registern an die Funktion übergeben.
    Und zweitens,hat auch die Reihenfolge in der die Parameter gepusht wurden nichts damit zutun in welcher Reihenfolge sie ausgewertet wurden.

    Das sind alles Freiheit die ein Compilerbauer hat,um die für sein System optimale Variante zu basteln.

    Nein! Das stimmt schon mit der reihenfolge: von rechts nach links)! Schau die den assembler code den gcc aus deinem programm generiert:
    beim ersten printf:
    die funktion f wird zuerst ausgeführt, dann das ergebnis davon auf den stack gelegt, dann das n.
    beim zweiten printf:
    es wird wieder zuerst f ausgeführt, dann jedoch das n auf den stack gelegt und dann erst der rückgabewert von f!
    Also im Zweifel für den Standard ^^,und der legt ganz klar keine Reihenfolge in der Auswertung der Parameter fest.
    Wenn du dich auf das verlässt was 'dein' Compiler darausmacht,dann siehst du alt aus,wenn du den Compiler wechselst.

  10. #10
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    O.k ich hab' mal den C Standard rausgekramt
    3.4.4
    1 unspecified behavior
    behavior where this International Standard provides two or more possibilities and
    imposes no further requirements on which is chosen in any instance
    2 EXAMPLE An example of unspecified behavior is the order in which the arguments to a function are
    evaluated.
    Klar .

  11. #11
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Ja,der Grund,daß das dort so steht ist der,daß früher (also in der IT-Steinzeit),Funktionparameter auf den Stack gepusht wurden.
    Nicht nur früher! Es ist heute genau so.
    Und zweitens,hat auch die Reihenfolge in der die Parameter gepusht wurden nichts damit zutun in welcher Reihenfolge sie ausgewertet wurden.
    Da stimme ich dir völlig zu! Das habe ich auch nicht gemeint. Vielleicht habe ich mich nur schlecht ausgedrückt. Ich meine die reihenfolge der übergabe von parametern.
    Wenn du dich auf das verlässt was 'dein' Compiler darausmacht,dann siehst du alt aus,wenn du den Compiler wechselst.
    Ich wage es mal zu sagen, dass es auch heute jeder c-compiler so macht (die reihenfolge meine ich). Schau dir doch das compilat, das dein compiler produziert. Ohne eine bestimmte reihenfolge wäre es doch garnicht möglich für die funktion selbst zu wissen wo den die parameter sind.

  12. #12
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    An example of unspecified behavior is the order in which the arguments to a function are
    evaluated.
    Ja. wie die parameter ausgewertet werden ist sch**ß egal. Aber nicht wie der compiler die parameter-übergabe realisiert.

  13. #13
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von TrollSlayer
    Ja. wie die parameter ausgewertet werden ist sch**ß egal. Aber nicht wie der compiler die parameter-übergabe realisiert.
    Aber,wie oben auch bereits geschrieben,werden (native Datentypen auf jedenfall),per Register übergeben,nicht per Stack.
    Und wenn die Funktion weiß,dass ihr erster Parameter im Register R10 liegt,dann ist wohl auch egal,in welcher Reihenfolge es dahin gelangt ist ^^.

    Und Parameter per Stack übergeben ist Standard,in Deep C Secrets von Peter van der Linden ist das für den sun Compiler schön beschrieben,

  14. #14
    Registrierter Benutzer
    Registriert seit
    15.08.2003
    Beiträge
    79
    Du sagst doch selbst:
    Und Parameter per Stack übergeben ist Standard

    So wird das auch gemacht. Würde man sie über register übergeben, was macht der compiler, wenn die cpu z.B. x register hat und die funktion aber x+1 parameter?

  15. #15
    Registrierter Benutzer
    Registriert seit
    24.06.2003
    Beiträge
    486
    Original geschrieben von TrollSlayer
    Du sagst doch selbst:

    Ne,sorry das sollte Register heißen.Sollte aus dem Kontext klar werden,

    Würde man sie über register übergeben, was macht der compiler, wenn die cpu z.B. x register hat und die funktion aber x+1 parameter?
    Ne,es ist schon Register (nicht Stack ^^,diesmal richtig).
    Kommentar aus Deep C Secrets
    Some C books make statements
    like "parameters are passed to a called function by pushing them on the stack from right to left." This
    is oversimplification—if you own such a book, tear out that page and burn it. If you own such a
    compiler, tear out those bytes. Parameters are passed in registers (for speed) where possible.
    und noch einer
    Although we talk about a "stack frame" being "pushed on the stack," an activation record need not be
    on the stack. It's actually faster and better to keep as much as possible of the activation record in
    registers. The SPARC architecture takes this to the limit with a concept called "register windows" in
    which the chip has a set of registers solely dedicated to holding parameters in procedure activation
    records.

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •