ZeigerA-rithmetik



  • Hallo Liebe C-Programmierer,

    folgender kleiner ProgrammTest stürzt ab. Wenn ich aber die Anweisungen ab ooo auskommentiere, dann stürzt es nicht ab. Ist das, was ich hier teste, überhaupt vorgesehen in C?
    (Da es um Zeiger geht, frage ich im C-Forum,auch wenn hier cout benutzt wird)
    (Visual Studio 2008, Windows XP)
    Vielen Dank schonmal für Eure Antwort!

    int main()
    {
    int a;
    int *b;
    a = 0;
    b = &a;

    b[0] = 11;
    cout << "b ist " << b << endl;
    cout << "b[0] ist " << b[0] << endl;
    cout << "*b ist " << *b << endl;
    cout << " " << endl;
    b++;
    b[0] = 22;
    cout << "b ist " << b << endl;
    cout << "b[0] ist " << b[0] << endl;
    cout << "*b ist " << *b << endl;
    cout << "b - 1 ist " << b - 1 << endl;
    cout << "b[-1] ist " << b[-1] << endl;
    cout << "*(b-1) ist " << (b-1) << endl;
    cout << " ------- " << endl; //ooo
    b++;
    b[0]=33;
    cout << "b ist " << b << endl;
    cout << "b[0] ist " << b[0] << endl;
    cout << "*b ist " << *b << endl;
    cout << "b - 1 ist " << b - 1 << endl;
    cout << "b[-1] ist " << b[-1] << endl;
    cout << "
    (b-1) ist " << (b-1) << endl;
    cout << "b - 2 ist " << b - 2 << endl;
    cout << "b[-2] ist " << b[-2] << endl;
    cout << "
    (b-2) ist " << *(b-2) << endl;
    cout << " " << endl;

    return 0;
    }



  • C++ in einem C-Subforum.
    Keine Codetags.
    Programm lässt sich nicht mal kompilieren, weil die Header fehlen.

    Und so vom drüberkucken machst du dir mit deinen Tests auch noch 1-A den Stack kaputt. Dass da was abstürzt, wundert mich gar nicht.



  • Hallo dachschaden,

    vielen Dank erstmal für Deine Antwort. Ich wollte bei dem vielen kot(e) zumindest auf den Header verzichten. Was meinst Du mit stack kaputtmachen?
    Weisst Du warum der Teil bis ooo (wohl zufällig) funktioniert bzw. nicht abstürzt und das ganze dann nicht?

    Freundliche Grüße
    cfrig



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C (alle ISO-Standards) in das Forum C++ (alle ISO-Standards) verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • cfrig schrieb:

    Ich wollte bei dem vielen kot(e) zumindest auf den Header verzichten.

    Deswegen die Codetags. Du kannst übrigens deine Beiträge editieren *nudge*nudge*.

    Normalerweise markiere, kopiere und füge ich den Code in Codetags direkt in eine Datei und prüfe erst mal, ob der Code überhaupt kompiliert. Ohne die Header geht das natürlich nicht. Siehe auch.

    cfrig schrieb:

    Was meinst Du mit stack kaputtmachen?

    Das heißt, dass bevor deine Variablen erstellt werden meist noch Zeugs auf den Stack gelegt wird - damit die Funktion zurückkehren kann, oder wo die Parameter gelegt werden, oder damit sie weiß, wie weit der Stack Pointer wieder zurückgesetzt werden muss, usw. Hängt meist vom ABI ab, wie die Daten genau aussehen.

    b ist ein Zeiger, den du auf a zeigen lässt. Nachdem du ein bisschen damit rumspielst, inkrementierst du b , sodass der Zeiger jetzt auf diese wichtigen Daten zeigt und schreibst dann 22 da rein. Damit machst du dir den Stack kaputt.

    Es kann auch sein, dass direkt vor deinen Daten ein sogenannter Canary (Kanarienvogel, die man in den Minen hatte als Indikator dafür, dass die Luft schlecht wurde) gesetzt wurde, und ein Stack Guard anschlägt. Keine Ahnung, ob VS2008 bereits so was implementiert hat. Im Zweifel ist es von C++ undefiniert. Mehr brauchst du auch nicht wissen, es sei denn, du machst Softwareanalyse auf Binärlevel.



  • Hallo dachschaden,

    danke für Deine ausführliche Antwort. Sie hat mir auf jeden Fall weitergeholfen.
    Eine letzte Frage: was, und welche Bücher, kannst Du empfehlen, um in C/C++ schnell soviel dazu zu lernen, um meine Ausgangsfrage selbst beantworten zu können bzw. zu wissen, dass man sowas in C/C++ gar nicht macht ?

    Freundliche Grüße
    cfrig


  • Mod

    Zuerst solltest du dir "C/C++" abgewöhnen. Du sprichst doch auch nicht von "Lateinisch/Italienisch" als eine Sprache. C und C++ haben zwar eine gewisse geschichtliche Verwandtschaft, aber sind komplett unterschiedliche Sprachen.

    Das ist dann auch ein ganz dickes Warnzeichen für schlechtes Lehrmaterial, wenn es von "C/C++" spricht. Ansonsten:
    Bücher und Tutorials zu C++
    Bücher von Jürgen Wolf sind zum Lernen ungeeignet



  • Hallo SeppJ,

    vielen Dank für Deine Antwort. Die von Dir angegebenen Links habe ich schon weitgehend durchgeschaut. Ich glaube, dass man, neben vielen Programmtests, auch durch Lesen in diesem Forum gut weiterkommt.
    Mit Deiner Trennung von C und C++ hast Du vom Programmierparadigma her natürlich Recht. Andererseits liest man immer wieder (und es ist wohl auch "allerweitestgehend" Tatsache), dass C quasi vollständig in C++ enthalten ist (ein C-Programm ist (quasi) immer auch ein C++-Programm). Das kann ich auch (weitestgehend) in Visual Studio feststellen, wenn ich ein lauffähiges C++-Projekt mit reinem C-Code erstelle.

    Kannst Du mir gute C-Bücher nennen (außer K&R) ?

    Freundliche Grüße
    cfrig


  • Mod

    C in C++ auszuführen gelingt vielleicht auf "Hello World"-Niveau, aber sobald du nur ein bisschen was Komplexes tust, wird es nicht mehr gehen. Sieh C und C++ als getrennte Sprachen an und sei skeptisch gegenüber jedem, der etwas anderes behauptet. Insbesondere ist C keine Lernhilfe für C++! Der manchmal empfohlene Pfad, über C zu C++ zu kommen, ist ein Holzweg.

    Ich kenne kein anderes C-Buch, das ich empfehlen würde, außer K&R.



  • cfrig schrieb:

    Andererseits liest man immer wieder (und es ist wohl auch "allerweitestgehend" Tatsache), dass C quasi vollständig in C++ enthalten ist (ein C-Programm ist (quasi) immer auch ein C++-Programm). Das kann ich auch (weitestgehend) in Visual Studio feststellen, wenn ich ein lauffähiges C++-Projekt mit reinem C-Code erstelle.

    Naja, ich würde mal sagen, dass "weitestgehend" nicht besonders weit kommt. Beispiel:

    #include <stdlib.h>
    
    int main() {
        int *a = malloc(sizeof(int));
        free(a);
    }
    

    Und C-Programme ohne malloc sind sehr selten. Und schon haben wir das Problem. Von daher würde ich mal behaupten, dass sich kein einigermaßen große C-Programm als C++ übersetzen lässt, es sei denn, es wurde von einem C++-Programmierer geschrieben.



  • Hallo SeppJ, hallo wob,

    vielen Dank für Eure Antworten. Ich lasse mich sehr gern belehren und nehme Eure Belehrungen aber auch deswegen an, weil ich sie, was die Praxis angeht, für richtig halte. Die Aussage, dass C in C++ enthalten ist, wird gar nicht selten an Unis oder FHs gelehrt (ist nur Kern-C (Sprachumfang) ohne die Bibliotheken gemeint?).

    Dennoch konnte ich folgendes, leicht modifizierte, "Programm" in Visual Studio 2008 fehler- und warnungsfrei kompilieren:

    #include <stdlib.h>
    
    int main() {
        int *a;
    	a=(int*)malloc(sizeof(int));
        free(a);
    }
    

    Freundliche Grüße
    cfrig


  • Mod

    Mit Casts kann man alles irgendwie so lange verbiegen, bis es funktioniert. Obiger Code hat zwar nun die gleiche Funktionalität wie das Original, aber du hast sämtliche Sicherheitsmechanismen der Sprache abgeschaltet. Ein falscher Code würde nun ebenso compilieren (und dann zur Laufzeit fehlschlagen) wie dieser richtige Code. Das ist ja wohl kaum im Sinne des Erfinders.

    Die Aussage, das C in C++ enthalten ist, hat schon ihre Herkunftsberechtigung, insofern als dass man
    1. Die Standardbibliothek von C, wie sie 1989 war, in C++ aufgenommen hat.
    2. In den Anfangszeiten von C++ versucht hat, möglichst kompatibel zu bleiben.

    Das ist aber alles 30 Jahre her und seither haben sich beide Sprachen unabhängig voneinander weiter entwickelt. Und die Punkte 1 und 2 waren bei diesen Entwicklungen auch nicht mehr so wichtig. Von Zeit zu Zeit hat man in beiden Sprachen auch mal nützliche Neuerungen der anderen übernommen, aber bei weitem nicht alle.

    Die von wob gezeigte Inkompatibilität ist sicherlich die wichtigste, weil jedes halbwegs komplexe C-Programm implizite Zeigerkonvertierungen benutzt, die in C++ nicht erlaubt sind. Ansonsten hat der C++-Standard ein ganzes Kapitel über Inkompatibilitäten mit C.

    Du kannst dich ja mal da dran versuchen, dieses vollkommen valide C-Programm (zugegeben: Es ist teilweise ziemlich schlechter C-Stil) als C++ zu übersetzen:

    #include <stdio.h>
    
    struct X { int i; struct X *next; };
    static struct X a;
    static struct X b = { 0, &a };
    static struct X a = { 1, &b };
    
    typedef int X;
    
    struct S
    {
      X x;
      int X;
    };
    
    enum color { red, blue, green };
    enum color c = 1;
    
    void arbitrary_args() {}
    
    void inline_type_def( struct S { int a; } arg ) {}
    
    struct W {
      struct Y {int i;} y;
    };
    struct Y yy;
    
    main(argc, argv)
    int argc;
    char *argv[];
    {
      if (sizeof(' ') > 1)
        puts("alles richtig");
      auto X virtual = 123;
      int vla[virtual];
      printf("main at: %p\n", &main);
      implicit_function(1, 1.2);
      char arr[100];
      if (sizeof(0, arr) == sizeof(char*))
        puts("Dies ist C");
      goto label;
      int initialized = 456;
      label:
      arbitrary_args(1,2,3);
      char array[4] = "abcd";
    }
    
    int implicit_function(int i, double d) {}
    

    Manche C++-Compiler werden manche der hier benutzten C-Features eventuell unterstützen. Also nicht wundern, wenn einzelne Zeilen ohne Änderung funktionieren 😃 . Das heißt aber noch lange nicht, dass sie gültiges C++ sind, dass überall funktioniert.
    Wie du vielleicht auch merkst, sind einige der hier demonstrierten Sachen relativ harmlos aussehend.



  • Hallo SeppJ,

    danke für Deine Antwort. Das von Dir angegebene C-Programm wird bei mir in Visual Studio 2008 nicht kompiliert und auch nicht in einem anderen reinen C-Compiler. Ich denke, dass es nichts bringt, jetzt detailliert auf die Fehlermeldungen der Compiler einzugehen.

    Aber im Prinzip hast Du Recht mit deinen Ausführungen.
    Ich kenne übrigens ein C-Programm, das nicht in meinem Visual Studio kompiliert wird, aber in meinem (zugegeben alten) C-Compiler und auch einwandfrei funktioniert:

    #include "stdio.h";
    int v,i,j,k,l,s,a[99]; 
    main () 
    { for(scanf("%d",&s);*a-s;v=a[j*=v]-a[i],k=i<s, 
    j+=(v=j<s&&(!k&&!!printf(2+"\n\n%c"-(!l<<!j), 
    " #Q"[l^v?(l^j)&1:2])&&++l||a[i]<s&&v&&v-i+j&&v+i-j)) 
    &&!(l%=s),v||(i==j?a[i+=k]=0:++a[i])>=s*k&&++a[--i]) 
    ; 
    }
    

    Es löst das n-Damenproblem (Schachbrett) und hat, wohl wegen seiner extremen Kompaktheit, mal einen Preis gewonnen.
    Ansonsten denke ich, dass meine Fragen sehr gut geklärt werden konnten und ich einiges gelernt habe.

    Freundliche Grüße
    cfrig


  • Mod

    Dann kann VS wohl weder die old style Funktionen (die sind auch nicht mehr offiziell, daher braucht ein C-Compiler das nicht zu können), noch C99 (weil Microsoft nicht auf C setzt). Ein "richtiger" C-Compiler hätte es schlucken sollen. Der Punkt, dass C keine strikte Untermenge von C++ ist, ist aber wohl vermittelt worden.



  • cfrig schrieb:

    int a;
    int b;
    a = 0;
    b = &a;
    ...
    cout << "b[-1] ist " << b[-1] << endl;
    cout << "
    (b-1) ist " << (b-1) << endl;
    cout << "b - 2 ist " << b - 2 << endl;
    cout << "b[-2] ist " << b[-2] << endl;
    cout << "
    (b-2) ist " << *(b-2) << endl;
    }

    Eieiei, was soll das denn? Da schüttelt es mich.



  • cfrig schrieb:

    Hallo SeppJ, hallo wob, [...]Ich lasse mich sehr gern belehren und nehme Eure Belehrungen aber auch deswegen an, [...] Die Aussage, dass C in C++ enthalten ist, wird gar nicht selten an Unis oder FHs gelehrt

    Und wenn mir jemand was Anderes erzählen wollte, wäre ich skeptisch.

    Daß C und C++ zwei vollkommen getrennte Sprachen seien, ist ausgemachter Käse.

    C++ ist historisch entstanden als objektorientierte, später auch generische, Erweiterung von C, und die Kompatibilität von C++ mit C ist weder Zufall noch unerwünschte Nebenwirkung, sondern ein Feature. Und was für eins!

    Die C-Kompatibilität ist eines der Features von C++, eines der wichtigsten. Denn damit war von Anfang an der Zugriff auf viele vorhandene C-Libraries sichergestellt, was dem Durchbruch von C++ geholfen haben dürfte.

    Mangel an vorhandenen Libraries ist nämlich ein Problem, das dem Durchbruch neuer Programmiersprachen öfters im Wege steht. Dieses Problem hatte C++ nicht. Dank C-Kompatibilität. Alles klar?



  • Hallo zufallswert,

    Dir auch vielen Dank für Deinen Beitrag. Ich denke, über das Ausmaß, die Ausprägung der Verschiedenheit von C und C++ kann man lange (endlos?) streiten und es ist wohl auch so, dass im
    Laufe der Zeit die Verschiedenheit eher zugenommen hat.
    Jedenfalls ist das, was Du schreibst, auch alles sehr richtig und plausibel.

    (Zu meinem ersten Beitrag von gestern (Testprogramm Zeigerarithmetik) muss ich schon heute sagen,
    dass es mir vorkommt wie wenn ein Kleinkind eine Glasflasche aus dem 3. Stock auf den Betonboden
    wirft, um zu sehen, ob sie auch wirklich kaputt geht. Es ist mir jetzt klar, dass über sowas nichts in irgendeinem Buch steht.)

    Nochmal vielen Dank an alle!


Log in to reply