Konvertierung von 'char * *' nach 'const char * *' nicht möglich
-
Hallo Leute,
Ich hab hier 'n ziemlich blödes Problem. Und irgendwie komm ich mir gerade ein wenig dumm vor, dass ich dazu keine Lösung finde (weil die glaube ich sehr einfach wäre).Also: Ich versuche mich gerade an der OpenGL-Funktion glShaderSource(). Als 3. Parameter erwartet sie einen "const char**"-Pointer. Natürlich will ich den GLSL-Code (der wird mit diesem Parameter übergeben) aus einer Datei laden, daher kann ich kein const verwenden.
Abgesehen davon, sollte es doch kein Problem sein, von nicht-const zu const zu konvertieren. Andersrum natürlich schon.
Turbo C++ beschwert sich mit folgenden Meldungen:
[C++ Fehler] glsl_unit.cpp(52): E2034 Konvertierung von 'char * *' nach 'const char * *' nicht möglich
[C++ Fehler] glsl_unit.cpp(52): E2342 Keine Übereinstimmung des Typs beim Parameter 'string' ('const char * *' erwartet, 'char * *' erhalten)Danke für Eure Hilfe!
Mr Train
-
Naja, nehmen wir mal an, dass das gehen würde, dann könnte ich folgendes tun
#include <iostream> using namespace std; int main() { char const a = 'a'; char const *pa = &a; char b = 'b'; char *pb = &b; char **ppb = &pb; char const **const_ppb = ppb; *const_ppb = pa; //jetzt steht in *const_ppb, also auch in *ppb: &a **ppb = '5'; //WHAT, ich kann ein const ändern? cout << static_cast<const void*>(&a) << " " << static_cast<const void*>(&*pa) << " " << a << " " << *pa; }Felix
-
Danke für deine Mühe, aber das ist doch etwas anderes. Bei mir gibt es eine Funktion, die als Parameter einen const-Wert erwartet. Da die Funktion davon ausgeht, dass der Wert nicht veränderbar ist, wird sie auch nicht versuchen ihn zu ändern. Deswegen ist es IMHO völlig in Ordnung einer Funktion, die einen konstanten Wert erwartet, einen variablen Wert zu übergeben.
Dein Beispiel macht genau das Gegenteil: Du hast eine Konstante, die du versuchst zu ändern - anstatt nicht zu versuchen eine Variable zu ändern.
Ich hoffe es ist jetzt klar geworden. Wie werde ich jetzt also diese Fehlermeldung los? Warum ist sie überhaupt da?
Ich freue mich über weitere Antworten.
Mr Train
-
Es könnte sonst folgendes passieren:
void Test(const char** test){ *test="Lala"; // Erlaubt, da test ja auf etwas konstantes zeigen soll } int main(){ char ** a; Test(a); *a[1]='B'; // Ups... Jetzt soll ein Literal geändert werden. }edit: Was jedoch ein bisschen komisch ist: Bei einfachen Pointern funktioniert obiges auch(nicht) wird vom Compiler jedoch angenommen, beim Ausführen jedoch mit einem entsprechenden Laufzeitfehler quittiert.
-
Jo, danke SeppJ.
Ich hab den Compiler jetzt ein bisschen ausgetrickst, indem ich der Funktion, die glShaderSource() aufruft, den Sourcecode als const-Parameter übergeben habe, den sie dann als Parameter für glShaderSource() verwendet. Etwas umständlich, aber naja es geht. 
Hier noch mein funktionierender Source-Code
// Global GLhandleARB ProgramObject; GLhandleARB VertexShaderObject; GLhandleARB FragmentShaderObject; char* VertexShaderText = NULL; // Nicht const char* FragmentShaderText = NULL; // Nicht const int VertexShaderLength = 0, FragmentShaderLength = 0; bool LoadShaders(const char* vs_src, const char* ps_src) // Parameter const { // Shader ProgramObject = glCreateProgramObject(); VertexShaderObject = glCreateShaderObject(GL_VERTEX_SHADER_ARB); FragmentShaderObject = glCreateShaderObject(GL_FRAGMENT_SHADER_ARB); glShaderSource(VertexShaderObject, 1, &vs_src, &VertexShaderLength); glShaderSource(FragmentShaderObject, 1, &ps_src, &FragmentShaderLength); // ... return true; } // Irgendwo im Init-Code LoadShaders(VertexShaderText, FragmentShaderText);Natürlich übergebe ich keine NULL-Zeiger an LoadShaders(), da wird vorher noch was aus einer Datei geladen

-
Mr Train schrieb:
Danke für deine Mühe, aber das ist doch etwas anderes. Bei mir gibt es eine Funktion, die als Parameter einen const-Wert erwartet.
Das stimmt ja nicht. Deine Funktion erwartet eine Zeiger auf einen Zeiger, der selbst variabel ist. Bei Aufrufer kann dieser Zeiger auf jedes beliebige modifizierbare Zeichen zeigen und man darf erwarten, dass diese Eigenschaft auch nach dem Funktionsaufruf erhalten bleibt. Innerhalb der Funktion (also const char**) haben wir es dagegen mit einem Zeiger zu tun, der sowohl auf modifizierbare als auch auf konstante Zeichen zeigt, der mögliche Wertebereich ist also größer, mithin ist es möglich, diesem Zeiger einen Wert zu geben, der beim Aufrufer unzulässig wäre, wie von Phoemix gezeigt - dieses Beispiel wird so auch im Standard angeführt. Möglich ist hingegen die Konvertierung von char** nach const char* const*
@SeppJ: meinst du den Fall void Test(char**) ? Dann ist das einfach die Folge der historisch bedingten Array-zu-pointer-Konvertierung für Stringliterale, bei der const verloren gehen kann.
-
camper schrieb:
@SeppJ: meinst du den Fall void Test(char**) ? Dann ist das einfach die Folge der historisch bedingten Array-zu-pointer-Konvertierung für Stringliterale, bei der const verloren gehen kann.
Stimmt. Ungünstig von mir, für das Beispiel char als Datentyp zu wählen. Damit es nochmal klarer wird, das gleiche nochmal mit int. Dann wird auch klar, wieso es erst bei pointer auf pointer einen Fehler gibt:
const int i=12; void Test(const int ** test){ *test=&i; } int main () { const int ** a; a = new (const int*); Test(a); cout << (**a) << endl; // 12, alles ok (**a) = 13; // verboten, weil const int ** b; b = new (int*); Test(b); // aus gutem Grund verboten cout << (**b) << endl; (**b) = 13; // Aua! Nun wäre diese Änderung nicht verboten. }