Was ist der Unterschied zwischen c beide Texte



  • @Wade1234 sagte in Was ist der Unterschied zwischen c beide Texte:

    @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    gezielt die Schleifen zu verlassen oder einen neuen Durchlauf anzustoßen.

    break, continue?

    Das geht immer nur in der innersten Schleife. Man kann bei mehrfachen Schleifen in C das nicht mehr nutzen und muss auf goto zurückgreifen. Da wohl einige mit Fortran überfordert sind, das gleiche Beispiel nun in C. An dieser konkreten Stelle könne man das goto natürlich durch ein break ersetzen. Hat man aber noch ein paar Schleifen dazwischen geht das nicht mehr, und die

    #include <complex.h>
    #include <stdio.h>
    #include <stddef.h>
    #include <stdlib.h>
    
    void nop() {
        return;
    }
    
    const size_t index (const size_t i, const size_t j, const size_t row_size) {
        return i*row_size+j;
    }
    
    void init_matrix(double complex *P, const size_t m, const size_t n, const double complex value) {
        for (size_t i = 0; i < m; ++i) {
            for (size_t j = 0; j < n; ++j) {
                P[index(i,j,n)] = value;
            }
        }
    }
    
    void print_matrix(double complex* p, const size_t m, const size_t n) {
        for (size_t i = 0; i < m; ++i) {
            for (size_t j = 0; j < n; ++j) {
                printf("(%2.2f,%2.2f)",creal(p[index(i,j,n)]),cimag(p[index(i,j,n)]));
            }
            printf("\n");
        }
    }
    
    int main() {
        const size_t s = 10;
        const size_t sdc = sizeof(double complex);
        const size_t acs = sdc*sdc*s*s;
        double complex* A = 0, *B = 0 , *C = 0;
        const complex cnull = CMPLX(0.0,0.0);
        const complex cone  = CMPLX(1.0,0.0);
    
        A = malloc(acs);
        B = malloc(acs);
        C = malloc(acs);
    
        if (!A || !B || !C) return EXIT_FAILURE;
    
        init_matrix(A,s,s,cnull);
        init_matrix(B,s,s,cone);
        init_matrix(C,s,s,cnull);
    
        for (size_t i = 0; i < s; ++i) {
            B[index(i,i,s)] = cone;
        }
    
        double x =  0.0;
        double y = 10.0;
    
        for (size_t i = 0; i < s; ++i) {
            x += 0.25;
            y -= 1.00;
            A[index(i,i,s)] = CMPLX(x,y);
        }
    
        print_matrix(A,s,s);
        printf("\n");
    
        for (size_t i = 0; i < s; ++i) {
            for (size_t j = 0; j < s; ++j) {
                double complex sl = cnull;
                for (size_t k = 0; k < s; ++k) {
                    sl += A[index(i,k,s)] * B[index(k,j,s)];
                }
                if (cabs(sl) > 7.0) goto outer_loop;
                C[index(i,j,s)] = sl;
            }
            outer_loop:
            nop();
        }
    
        print_matrix(C,s,s);
    
        free(C);
        free(B);
        free(A);
    
        return EXIT_SUCCESS;
    }
    
    

    @Swordfish sagte in Was ist der Unterschied zwischen c beide Texte:

    @john-0 Jo, Johny, schon klar. Ich lerne jetzt mal eben auf die schnelle FORTRAN um dir eine Gegenrede in einem C-Forum geben zu können. Sag' mal, ist schon Weihnachten!?

    Überfordert das bisschen Code in Fortran? Sorry, aber das sollte eigentlich ohne konkrete Sprachkenntnisse nachvollziehbar sein.



  • @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    An dieser konkreten Stelle könne man das goto natürlich durch ein break ersetzen. Hat man aber noch ein paar Schleifen dazwischen geht das nicht mehr

    break und flag oder return.

    @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    Überfordert das bisschen Code in Fortran? Sorry, aber das sollte eigentlich ohne konkrete Sprachkenntnisse nachvollziehbar sein.

    Die Mühe mache ich mir garnicht erst. Wozu auch. Dein Hinweis das solcher code im HPC Umfeld verbreitet wäre ist lachhaft. Das geht viel besser.

    for (size_t j = 0; j < s && cabs(s1) <= 7.0; ++j) {
    

    und all Deine Probleme sind gelöst. Ohne goto.



  • @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    Das geht immer nur in der innersten Schleife. Man kann bei mehrfachen Schleifen in C das nicht mehr nutzen und muss auf goto zurückgreifen.

    man muss kein goto benutzen, wenn man es nicht will. wenn du so riesige schleifenkonstrukte hast, solltest du die ganzen anweisungen in funktionen auslagern und ganz streng genommen, sollte man im hauptprogramm überhaupt keine direkten anweisungen haben, weil dies a) den lesefluss bzw. das verständnis sehr erheblich stört, b) die wahrscheinlichkeit relativ hoch ist, dass man diesen programmcode auch an anderer stelle brauchen könnte und c) man das programm so relativ unkompliziert verändern kann.

    ein vernünftiges hauptprogramm könnte daher so aussehen (evtl. mit besseren funktionsnamen):

    int main()
    {
         BenutzereingabeAbfragen();
         BenutzereingabeAufbereiten();
         BenutzereingabeVerarbeiten();
         ErgebnisDerVerarbeitungAusgeben();
    
         return 0;
    }
    

    wie du siehst ist das programm sehr kurz und übersichtlich, obwohl es theoretisch milliarden codezeilen in den einzelnen funktionen und deren unterfunktionen haben könnte.

    aber du siehst auf den ersten blick, was das programm macht, du kannst ganz unkompliziert eine weitere funktion einfügen oder auch eine funktion verändern, ohne dass die anderen funktionen davon betroffen sind.

    wenn du goto verwendest, ist das einfach schlechter stil. wenn die linuxentwickler goto verwenden, ist das auch schlechter stil. bei c versucht man die hauptaufgabe in verschiedene unteraufgaben zu unterteilen und diese unteraufgaben versucht man auch wieder in unteraufgaben zu unterteilen, bis es irgendwann einfach nicht mehr weiter geht, weil man ab dort bspw. auf funktionen des betriebssystems zugreifen oder inline-assembler verwenden muss oder dort die eigentlichen berechnungen ausgeführt werden sollen und dafür brauchst du schleifen, verzweigungen und funktionen, mehr nicht.



  • @Swordfish sagte in Was ist der Unterschied zwischen c beide Texte:

    for (size_t j = 0; j < s && cabs(s1) <= 7.0; ++j) {
    

    und all Deine Probleme sind gelöst. Ohne goto.

    Leider falsch,
    hier wird eine lokale Variable (auch bei einem Flag) in den Schleifenkopf gezogen und so deren Lokalität zerstört. Das hat bei parallelisierten Schleifen verheerende Folgen.

    Ersetzt man die zentrale Schleife mit so einer Schleife (OpenMP parallelisiert), sieht man schnell, dass Flags bzw. Testen nicht sinnvoll ist. Mit einer anderen Parallelisierung (pthreads o.ä.) gibt's die gleichen Probleme.

        #pragma omp parallel for default(none) shared(A,B,C)
            for (size_t i = 0; i < s; ++i) {
                for (size_t j = 0; j < s; ++j) {
                    double complex sl = cnull;
                    for (size_t k = 0; k < s; ++k) {
                        sl += A[indx(i,k,s)] * B[indx(k,j,s)];
                    }
                    if (cabs(sl) > 7.0) goto outer_loop;
                    C[indx(i,j,s)] = sl;
                }
                outer_loop:
                nop();
            }
    


  • @Wade1234 sagte in Was ist der Unterschied zwischen c beide Texte:

    sollte man im hauptprogramm überhaupt keine direkten anweisungen haben

    Weshalb sollte ich in kurzen compilierbaren Beispielen noch mehr Indirektionen einbauen? Es ist kein realer Code sondern soll nur einen Effekt zeigen. Es ist schon Luxus, dass das ganze übersetzbar ist und als Programm ausführbar ist.



  • @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    Es ist schon Luxus

    Das ist kein Luxus sondern erwarteter Mindeststandart.

    @john-0 sagte in Was ist der Unterschied zwischen c beide Texte:

    parallelisierten Schleifen

    Hast Du mit keinem Wort vorher erwähnt. Auch dafür gibt es Lösungentm.



  • @Swordfish sagte in Was ist der Unterschied zwischen c beide Texte:

    Hast Du mit keinem Wort vorher erwähnt. Auch dafür gibt es Lösungentm.

    Weshalb so eine ideologische Einstellung zum Thema goto? Es gibt gute Gründe es außerhalb der Schleifenproblematik und des Error-Handlings in C nicht mehr zu nutzen. Aber wie Du siehst, hat die zwanghafte Vermeidung von goto Seiteneffekte, die sehr hässlich werden können. Weshalb diese dogmatische Haltung zu diesem Thema?



  • hatten wir das mit dem ausstieg aus den schleifen bzw. sofortiger fehlerbehandlung nicht schonmal? für jede schleife eine funktion und wenn fehler auftreten, wird die funktion einfach mit fehlercode verlassen und die übergeordnete funktion "weiß bescheid".



  • @Wade1234 sagte in Was ist der Unterschied zwischen c beide Texte:

    hatten wir das mit dem ausstieg aus den schleifen bzw. sofortiger fehlerbehandlung nicht schonmal?

    das hatten wir schon x-mal.



  • @Swordfish
    Ja aber ich meinte damit, dass speziell wir drei uns vor einem Monat oder so bereits darüber unterhalten haben, dass man bei verschachtelten Schleifen und Fehlerbehandlung eben kein goto braucht und im Regelfall ändern sich Prinzipien nicht alle 4 Wochen......


Log in to reply