Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

20.04.2012, 16:07

char * als funktionsparameter

Hi Leute,

so, inzwischen habe ich Listing 8.14 und auch das Problem mit der Unicode-Einstellung einigermassen verstanden. Was
mir aber noch nicht in den Kopf will :dash: , ist die bestimmte Verwendung von Zeigern in dem Listing.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//C++ f. Spieleprogrammierer
//Test 
//
#include <iostream>

using namespace std;

void TextAusgabe (const char *);        //Prototyp

int main ()
{
    TextAusgabe ("Hallo Welt");

    cout << endl;

    return 0;
}

//TextAusgabe
void TextAusgabe (const char *Text)
{
    cout << Text << endl;
}//TextAusgabe


1. Frage
Hier habe ich diese Zeigerverwendung für mich in eine einfache Funktion verpackt. Man kann also anscheinend einer Funktion im Prototyp sowie in der Definition einen Char-Parameter als Zeiger übergeben, und im Funktionsaufruf dann einfach einen Text als Parameter weiter geben, anstatt einer Adresse 8| . Mit z.B. int funktioniert das nicht...ist das so eine spezielle Funktion von C++, die im Buch bis anhin einfach noch nicht weiter erläutert wurde, oder übersehe ich da einen logischen Zusammenhang?

2.Frage
Im Prototyp muss ich ja eigentlich nur die Datentypen als Parameter angeben. Will ich der Funktion aber einen Zeiger übergeben, muss noch der Indirektionsdingsbums * dazu geschrieben werden. Ist also z.B. char * ein eigener Datentyp, welcher sich von char unterscheidet, oder ist char der Datentyp, und bei Zeigern muss halt eben doch auch im Prototyp noch die weitere Angabe in Form des * gemacht werden...ich hoffe, ihr versteht meine Frage ;)

2

20.04.2012, 16:35

char* sind sog. C-Strings. In C ist ein "Stringobjekt" ein Array aus Charatkers und Arrays spricht man über den Zeiger auf das erste Element an. Anstatt also das Array zu kopieren, wird nur die Adresse kopiert und dann benutzt, um den String anzuzeigen.
cout kennt dieses Verhalten und behandelt deshalb char-Zeiger anders als andere Zeiger, indem sie als Strings interpretiert werden.

Besser ist es allerdings, C++ Stringobjekte zu benutzen. Das sähe dann so aus:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//C++ f. Spieleprogrammierer
//Test 
//
#include <iostream>
#include <string>  //<- Damit std::string bekannt ist!

using namespace std;

void TextAusgabe (string);        //Prototyp

int main ()
{
    TextAusgabe ("Hallo Welt");

    cout << endl;

    return 0;
}

//TextAusgabe
void TextAusgabe (string Text)
{
    cout << Text << endl;
}//TextAusgabe


Ich denke, so ist das klarer und verständlicher.

Und ja, char und char* sind verschiedene Typen und man kann sie nicht einfach mischen oder so.
Lieber dumm fragen, als dumm bleiben!

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

3

20.04.2012, 16:53

std::string sollte, wie alle komplexen Datentypen in der Regel als referenz übergeben werden.
Also bitte:
void TextAusgabe (const string &Text)
Sonst wird der String einmal unnötig kopiert.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

4

20.04.2012, 18:03

@Jonathan: vielen Dank für die ausführliche Erklährung..jetzt ists mir so in etwa klar! Da kann ich natürlich lange im Buch bei den Zeigern rumlesen..solche char-strings kamen bis jetzt einfach noch nicht vor, meiner Meinung nach ;) ausser eben in listing 8.14

wegen dem Hinweis von nachoman: stimmt das: einmal wird, wenn der String nicht als Referenz übergeben wird, der String für den Funktionsparameter kopiert, und dann vom Funktionsparameter in die Funktion für die cout-Ausgabe..?

5

20.04.2012, 18:07

Ja, das hast du richtig verstanden. Wenn du den String jedoch als (konstante) Referenz übergibst, wird nur die Speicheradresse "kopiert" und dann beim std::cout an dieser "Adresse" nachgeschaut, was für ein Wert dort steht. Man spart sich also die eine Kopie, bei komplexen Objekten kann das viel ausmachen, wenn sie häufig verwendet werden.

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

6

20.04.2012, 18:12

Wenn du den String so übergibst:

C-/C++-Quelltext

1
2
3
4
void TextAusgabe (string Text)
{
    cout << Text << endl;
}

Wird er kopiert. Es ist also fast das selbe wie...

C-/C++-Quelltext

1
2
3
4
5
void TextAusgabe (const string& Textparam)
{
    string Text(Textparam);
    cout << Text << endl;
}

Hier ist das Erzeugen einer Kopie klarer zu erkennen. Das ist aber nicht nötig, weil du den String nicht bearbeiten musst.
Da der streamoperator << von cout auch einen const string& entgegennimmt wird in meiner empfohlenen Variante also nur einmal kopiert(beim umwandeln des c-strings in einen std::string).
Machst du es so wie oben wird der String zwei mal kopiert, was bei längeren Texten sehr lang dauern kann. Wenn du später mit Grafiken oder sogar Videos arbeitest können bei einer Übergabe als Wert schonmal zweimillionen Byte(2mb) oder noch viel mehr kopiert werden.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

7

20.04.2012, 20:47

Stimmt, das mit der Referenz hätte ich natürlich auch direkt einbauen können. Aber man kann natürlich argumentieren:

- das es (std::) string Implementierungen gibt, die einen von mehreren Objekten genutzten internen Buffer haben, so dass das kopieren nicht wirklich teurere ist, als die Übergabe per Referenz, und erst das Verändern des Strings teuer wird (weil er dann erst kopiert werden muss, damit andere String Objekte, die bisher den Speicher mitgenutzt haben nicht verändert werden).
- bei der Zeit, die cout für die Ausgabe braucht, die Zeit für das Kopieren egal ist

Grundsätzlich sollte man natürlich immer überlegen, ob man Parameter als Zeiger, Referenz oder Wert übergibt, aber einem sollte auch klar sein, wann das überhaupt einen messbaren Unterschied macht.
Lieber dumm fragen, als dumm bleiben!

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

8

20.04.2012, 21:05

Es sind eben nicht alle implementierungen so aufgebaut und
Eine einfache Regel ist besser als immer neu zu überlegen ob man eine Referenz oder eine Kopie übergibt weil:
- Anfänger das oft nicht einschätzen können
- konsistenter Code zu bevorzugen ist
- die Adresse auf das Objekt beim Optimieren öfter in die Register geschoben wird. Auch wenn das Objekt genau so groß oder sogar kleiner als der Zeiger ist.
- man oft nicht weiß, ob das Objekt durch Erweiterungen später doch einen größeren Kopieraufwand hat.

Wir haben sehr oft Threads in denen Code gepostet wird, in denen ganze Images als Wert übergeben werden, was oft zu weit mehr als Performanceeinbüßen führt. Es schadet nicht diese einfache Regeln schon früh zu kennen:
Elementare Datentypen wie int, char als Wert.
Komplexe Datentypen wie string, vector usw. oder eigene Datentypen(Klassen und Strukturen) als (konstante) Referenz.
Zeiger nur als Parameter verwenden, wenn auch kein Objekt (also NULL) erwartet und darauf geprüft wird.

Für jede Regel gibt es natürlich Ausnahmen. Die sollte man aber nur machen wenn man weiß was man tut.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (22.04.2012, 19:30)


Werbeanzeige