zum Inhalt springen

Erhellendes zur C++ ZP-Beispielaufgabe

Auf der HKI-Seite ist als ZP-Beispielaufgabe folgendes zu finden:

-------

 

#include <iostream.h>


int main()
{

char *beispiel[] =

{

"Rhabarberkompott", "Unternehmensberatung", "An dem Rhein", "So in Köln im Brauhaus", "Der Wahlbetrug", "Volle Besinnung", "Auftragsannahme", "Rhabarber am Stück", "Der Eigensinn als Stilmerkmal"

};

for (int i=8;i>0;i--) cout << (*(beispiel+i))[12-i];

cout << endl;

}

 

Welche Ausgabe wird durch dieses Programm produziert?

-------

siehe: http://www.hki.uni-koeln.de/?q=node/32 (etwa bis zur Mitte scrollen)

 

Letztens im Tutorium

Da saßen wir nun und schauten uns exakt diese Anweisung an:

(*(beispiel+i))[12-i]

Was es macht, war weniger das Rätsel, sondern: Was steht da syntaktisch eigentlich?

 

Das Experiment

Flott ein Beispiel gebastelt:

#include <iostream>
using namespace std;

int main()
{
    char* A[]=
    {
        "abc",
        "def",
        "ghi"
    };

    cout    << A            << " "      << *A                 << endl
               << A[0]       << " "      << *A[0]             << endl
               << A+1       << " "      << *A+1              << endl
               << (A+1)     << " "      << (*A+1)[0]       << endl      
               << (*(A+1)) << " "     << (*(A+1))[0]  << endl;
}

Das ergibt (z.B.) folgende Ausgabe:

0xbf91483c    abc
abc              a
0xbf914840    bc
0xbf914840    b
def                  d

Man beachte also: die Dereferenzierung erfolgt hier auf den Inhalt des Zeigers, der erstmal einen Array repräsentiert. Ein Array wiederum (man erinnere sich) ist im Grunde genommen ein Zeiger auf das erste Element des jeweiligen Index.

 

Der Unterschied zwischen *A+1 und (*(A+1))

Na klar, das eine heißt "Derefernziere zuerst Speicher A und dann eins weiter", ergo Ausgabe: bc

Das andere macht durch die Klammerung klar:
"Nimm Speicher A und eins weiter, dereferenziere erst dann". Der nächste Speicher ist hier jedoch das nächste Element im Array, also: def.

 

Hier der ASCII-Art Versuch einer Visualisierung:

A[0]               A[1]             A[2]
->                  ->                ->
[ [a][b][c] ]    [ [d][e][f] ]    [ [g][h][i] ]
   /\                  /\                 /\
   *A[0]            *A[1]            *A[2]

*A    *A+1      (*(A+1))
->    ->          ->
[ [a][b][c] ]    [ [d][e][f] ]    [ [g][h][i] ]
       /\       
       (*A+1)[0]     

 

Beachte hierr: wenn A+1 die Startadresse vom Array-Element (konstanten) Zeichenketten-Literal "def" repräsentiert, dann ist (*(A+1)) die Dereferenzierung vom String (und eben nicht nur die Startadresse).

(Html Ausgabe ist evt. etwas ungenau; daher vgl. mit Ausgabe oben oder selbst kompilieren und rumspielen.)

Auch mal hier nachlesen:
http://userpage.fu-berlin.de/~ram/pub/pub_jf47ht80Ht/c++_feld_de

Ach, Kinners, et is' manchmal nich' ganz einfach! ;)