[c++] const char und char* probleme?

4 Antworten

Vom Fragesteller als hilfreich ausgezeichnet

Die Codeformatierung hier auf GF hat deinen Code so versaut, dass alle bisherigen Antwortenden deine Frage komplett missverstanden haben.

Ich wette, dein Code sollte eigentlich so aussehen:

char * s = "Hello, world!";

Und das ist kein gültiges C oder C++, sodass dir jeder vernünftige Compiler eine Warnung bzw. Fehlermeldung ausgeben wird! Soweit also kein Wunder! ;)

Der Grund dafür ist, dass "Hello, world!" ein konstanter Literal ist. Dieser wird vom Compiler in einem Speicherbereich abgelegt, der nicht schreibbar, bzw. nur lesbar ist. (Das ist zwar genau genommen Plattform- und Compilerabhängig, erspart einem aber viel Kopfzerbrechen, wenn man das im Hinterkopf behält.)

Die Adresse des String-Literals "Hello, World!" kann also nur einem Zeiger zugewiesen werden, der auf "unveränderliche" (aka "konstante") Speicherbereiche zeigt.

Deshalb ist nur (!) das hier richtig:

const char * s = "abc";

Falls du hingegen - was oft vorkommt - den String nach der Zuweisung auch noch bearbeiten / verändern willst, solltest du den konstanten Literal "Hello, world!" dazu nutzen, um ein Array mit automatischer Größe zu initialisieren:

char s[] = "abc";

Jetzt könntest du ganz legitim irgendwo in deinem Code ...

s[0] = 'd':
s[1] = 'e';
s[2] = 'f';

... schreiben, sodass dein String jetzt "def" enthält. Das geht, weil der Compiler so ein Array eben NICHT im Speicher für unveränderliche Werte ablegt.

Beachte bitte auch, dass das Array nicht die Größe 3, sondern die Größe 4 hat, da implizit ein abschließendes Nullzeichen '\0' an der vierten Position mit Index 3 (s[3]) steht.

Das ist einer der vielen gravierenden Unterschiede zwischen Zeigern und Array, die von Einsteigern gerne mal durcheinander gebracht werden. Du bist also nicht der einzige, mit diesem Problem. :)

Beachte bitte auch, dass "const char *" ein "Zeiger auf ein konstantes Zeichen" und kein "Zeiger auf ein Zeichen", geschweige denn ein "konstanter Zeiger auf ein Zeichen" oder ein "konstanter Zeiger auf ein konstantes Zeichen" ist! ;)

Wenn du jetzt verwirrt bist, hier ein paar Beispiele:

char * s; // Zeiger auf Zeichen: beide veränderbar
const char * s; // Zeiger auf konst. Zeichen: nur Zeiger veränderbar
char * const s; // konst. Zeiger auf Zeichen: nur Zeichen veränderbar
const char * const s; konst. Zeiger auf konst. Zeichen: nichts änderbar

Ein guter Trick dabei ist, die Definition rückwärts (!) zu lesen. Die vierte Zeile vom vorherigen Beispiel würdest du dann lesen als: "s ist ein konstanter Zeiger auf eine char-Konstante".

Merk dir diese Eselsbrücke, denn sie wird dir die Arbeit oft stark erleichtern! (Bei Arrays und Funktionszeigern funktioniert das nicht ganz so einfach, aber das würde jetzt den Rahmen sprengen, also lassen wird das jetzt mal unter den Tisch fallen.)

Falls dir das jetzt alles noch nicht schlüssig erscheint, keine Sorge! Lern einfach weiter, und irgendwann macht es dann schon "Klick".

Fazit: Strings, die du nicht mehr verändern willst, als konstante Zeiger deklarieren, ansonsten als Array. So einfach ist das! ;)

Schönen Tag noch! :)

PS: Die obigen Aussagen beziehen sich größtenteils auf den reinen C-Teil von C++. Wenn du irgendwann mal fortgeschritten bist, solltest du - wie andere schon geschrieben haben - für Strings die entsprechende Klasse aus der STL nutzen, also ::std::string aus <string>.

Trotzdem ist es natürlich enorm wichtig, erst mal die Basics zu kennen und zu verstehen, wozu natürlich auch die Unterschiede zwischen Zeigern und Arrays zählen. :)

Nachtrag: Noch etwas zu ...

vam.Process("csgo.exe");

... aus deiner Frage.

Ich weiß nicht, welchen Typ das Objekt "vam" hat, aber wenn eine Funktion (oder ein Konstruktor) einen C-String erwartet, der als nicht-Output dient, und den Parameter NICHT als "const" deklariert, ist das ein eindeutiges Zeichen dafür, der / die Entwickler dieser Bibliothek keine Ahnung von dem haben, was sie da eigentlich tun. :)

Wenn also der Konstruktor so ähnlich wie ...

VAM::Process(char * exe);

... deklariert ist, dann sollte jedem Entwickler sofort klar sein, dass man damit keine Objekte mit Stringliteralen initialisieren kann. (Es gilt hierbei natürlich das gleiche, wie in meiner Antwort weiter oben beschrieben.)

0
@TeeTier

vam.Process(); ist ja mein eigentliches problem.

ProcMem vam;

Die variable vam ist von ProcMem.

Habe auch mal ein blick in die Datei (ProcMem.cpp - welche nicht von mir ist) geworfen und es sieht wie folgt aus:

void ProcMem::Process(char* ProcessName)
{
	HANDLE hPID = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
	PROCESSENTRY32 ProcEntry;
	ProcEntry.dwSize = sizeof(ProcEntry); 
	do
	    if(!strcmp(ProcEntry.szExeFile, ProcessName))
		{
			dwPID = ProcEntry.th32ProcessID;
			CloseHandle(hPID);
	        hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); 
			return;
		}
	while(Process32Next(hPID, &ProcEntry));

	cout << "\nCouldn't find game\n";
	system("pause");
    exit(0);
}

Und so wie ich es verstehe muss ich eine variable machen wo der Zeiger auf Zeichen ist (Siehe dein beispiel: char * s;) und diese halt mit (in meinem Fall) "csgo.exe" initialisieren (?).

Und ja. Wenn man code in GF postet, kommt oft was komischen raus...habe mal gehabt dass überall im code sowas wie &uos; oder so stand.

War eine sehr hilfreiche antwort! vielen dank!

1
@FynnFynn1334

Ja, das ist exakt das, was ich vermutet habe. Der Autor deiner Bibliothek und damit der Funktion "Process()", hat einfach einen Fehler gemacht, da der Parameter "ProcessName" tatsächlich ausschließlich lesend genutzt wird.

Das ist ein ganz klarer und handfester Bug. Mach dir also keinen Kopf, da kannst du gar nix für! Der Workaround besteht tatsächlich darin, ein entsprechendes Array zu übergeben:

char csgo[] = "csgo.exe";
vam.Process(csgo);

Das ist zwar unschön, geht hier aber leider nicht anders, da es sich ja nicht um deine eigene Bibliothek handelt.

Und dass der GF-Editor hier seit jeher total verbuggt ist, ist auch kein Geheimnis ... normalerweise wird hier JEDER Quelltext irgendwie entstellt, von einfachsten und sehr kurzen Snippets mal abgesehen. :)

0

char ist ein Wert. 8 oder 16 Bit- glaube ich.

char* ist ein Zeiger auf einen solchen Wert, wobei man, wenn man so einen bekommt annimmt, dass danach noch mehr Zeichen gefolgt von einem nullzeichen kommen. Char-Pointer sind auch als Strings oder Zeichenketten bekannt.

char ist ein einzelnes Zeichen, und du versuchst einen ganzen String darin zu speichern. Ein String ist eine Anzahl von einzelnen chars, willst du mehrere chars speichern brauchst du entweder ein char-Array oder einen String...

ok...bei string (Habe auch String versucht) sagt er (Visual Studio) dass der bezeichner String nicht defeniert ist

0
@user373h383

also es funktioniert so halb. kann die variable initialisieren ohne Probleme, aber ich muss diese als Argument "übergeben" (an vam.Process(); ), und jz bekomme ich beim übergeben den feheler: "Fehler (aktiv) E0167 Das Argument vom Typ ""const char *"" ist mit dem Parameter vom Typ ""char *"" inkompatibel."

0
@FynnFynn1334

Also const CString s = "Hello World";

oder evtl

vam.Process(s.getBuffer());

Strings unter c++ sind so eine Sache, schon alleine ob du unicode oder multibyte in deinem Projekt eingestellt hast macht einen großen Unterschied. Ließ dir am besten mal einen Beitrag dazu durch.

0

char (ohne Sternchen) ist ein einzelnes Zeichen (Byte oder Doppelbyte), das direkt im Speicher abgelegt wird.

char * (mit Sternchen) ist ein Zeiger auf die Speicherzelle, in der das Zeichen abgelegt wird. So was ähnliches wie ein Hyperlink auf einer Webseite oder eine Seitenangabe im Stichwortverzeichnis.

Steht da wirklich ""const char"" oder ""const char *"" ?

Und bitte, gewöhn dir von Anfang an an, die Möglichkeiten von C++ auszuschöpfen, etliche Fehler von C zu umgehen. Insbesondere nimm string statt char[] oder char* und nimm vectors statt arrays, solange du die höhere Geschwindigkeit von arrays nicht wirklich brauchst. Mögliche Fehlerquellen einzubauen hat man immer noch genug Gelegenheit, wenn man eine Sprache erst einmal beherrscht.

Woher ich das weiß:Berufserfahrung – Software-Entwickler

oh, da steht ""const char*""....und vielen dank für die tipps!

1
@FynnFynn1334

Ha! Ich habs gewusst! Das war der GF-Editor mal wieder. (siehe meine Antwort) :)

1