olpo schrieb:> Selbstverständlich ist das nicht der eigentliche Code, sonder> vereinfachter.
Der leider den Fehler nicht mehr enthält...
Dein Problem ist aber einfach nur "-Werror", das alle Warnings in Errors
verwandelt und damit den Compiler abbricht.
Jim M. schrieb:> Der leider den Fehler nicht mehr enthält...
Das habe ich mir schon gedacht.
Aber das sagt der Compiler: Argument 1 des Aufrufs "discards ‘const’
qualifier from pointer target type".
Also müssten die gezeigten Code-Teile doch reichen, oder?
Jim M. schrieb:> Dein Problem ist aber einfach nur "-Werror"
Naja, Werror und pedantic sind nun mal gesetzt im dem Projekt, und so
soll es auch bleiben.
olpo schrieb:> Aber das sagt der Compiler: Argument 1 des Aufrufs "discards ‘const’> qualifier from pointer target type".> Also müssten die gezeigten Code-Teile doch reichen, oder?
Nur, wenn der Compiler bei anderen die gleiche Fehlermeldung bringt. Bei
mir bspw. sagt der Compiler aber
1
test.c:1:13: error: ‘extensions_print’ used but never defined [-Werror]
olpo schrieb:> Jim M. schrieb:>> Der leider den Fehler nicht mehr enthält...>> Das habe ich mir schon gedacht.>> Aber das sagt der Compiler: Argument 1 des Aufrufs "discards ‘const’> qualifier from pointer target type".> Also müssten die gezeigten Code-Teile doch reichen, oder?
Nein, denn die produzieren diese Warnung nicht. Oder hast du tatsächlich
genau diesen Code mal durch den Compiler laufen lassen und dabei die
Warnung erhalten?
Merke: Immer zur Fehlermeldung passenden Code posten und nicht irgendwas
anderes, das einen Compiler nie gesehen hat.
Es geht dem OP wahrscheinlich nicht darum, die Fehlermeldung irgendwie
wegzubekommen, sondern den dahinterliegenden potentiellen Fehler zu
beseitigen. Man kann auch die nervige Ölwarnleuchte am Auto überkleben.
Stefan schrieb:> Ich würde vermuten, dass der String immer ein (char *) ist
Ein (char *) lässt sich einem (const char *) Parameter ohne Warnung
zuweisen. Hier scheint es der Meldung nach zu schliessen aber umgekehrt
zu sein.
olpo schrieb:> ich steh grad auf dem Schlauch.> static void extensions_print( const char *title);>> main(void)> {> extensions_print( "eiscreme" );> return 0;> }
ich stehe auch grad auf dem Schlauch,
wieso wird eine char* const deklariert wenn sie doch nicht const ist?
olpo schrieb:> error: passing argument 1 of ‘extensions_print’ discards ‘const’
da würde ich auch meckern
mit der Deklaration:
static void extensions_print( char *title );
würde mir das besser gefallen, weil eben char *titel nicht konstant ist.
vielleicht klärt mich ein C Kundiger auf?
Joachim B. schrieb:> wieso wird eine char* const deklariert wenn sie doch nicht const ist?
(const char *) ist ein Pointer auf einen nicht zu verändernden String.
Es schadet somit nicht, diesem Pointer einen potentiell variablen String
zuzuweisen. Nur umgekehrt ist nicht zulässig.
Etwas perfide ist allerdings, dass in C ein lexikalischer String "abc"
vom Typ (char []) statt (const char []) ist. Grund hierfür ist, das
"const" erst mit ANSI C nachträglich in die Sprache eingefügt wurde. In
C++ wurde das geändert.
A. K. schrieb:> Etwas perfide ist allerdings, dass in C ein lexikalischer String "abc"> vom Typ (char *) statt (const char *) ist. Grund hierfür ist, das> "const" erst mit ANSI C nachträglich in die Sprache eingefügt wurde. In> C++ wurde das geändert.
dann müsste doch folgender code eine Warnung erzeugen?
1
#include<stdio.h>
2
3
voidfoo(constchar*c)
4
{
5
printf("%s",c);
6
}
7
8
intmain()
9
{
10
foo("bar");
11
}
kommt bei mir zumindest nicht, kann es sein das es bei C auch schon
geändert wurde?
A. K. schrieb:> Joachim B. schrieb:>> wieso wird eine char* const deklariert wenn sie doch nicht const ist?>> (const char *) ist ein Pointer auf einen nicht zu verändernden String.> Es schadet somit nicht, diesem Pointer einen potentiell variablen String> zuzuweisen. Nur umgekehrt ist nicht zulässig.
da ich das immer noch nicht verstehe nur folgendes:
wäre dieses richtig und würde den genannten Fehler verschwinden lassen?
static void extensions_print( char *title );
dann wäre für mich das "Problem" gelöst.
ich würde nur dann const wählen wenn mein String so aussehen würde
const char title[]={"Text"};
und sich nie ändert
A. K. schrieb:> Peter II schrieb:>> dann müsste doch folgender code eine Warnung erzeugen?>> Weshalb?
oh stimmt, also bitte post vergessen - falsch rum gedacht.
C99 Rationale:
6.4.5: String literals are not required to be modifiable. This
specification allows implementations to share copies of strings with
identical text, to place string literals in read-only memory, and to
perform certain optimizations. However, string literals do not have the
type array of const char in order to avoid the problems of pointer type
checking, particularly with library functions, since assigning a
pointer to const char to a plain pointer to char is not valid. Those
members of the C89 Committee who insisted that string literals should be
modifiable were content to have this practice designated a common
extension (see §J.5.5).
J.5 Common extensions:
J.5.5 Writable string literals
String literals are modifiable (in which case, identical string literals
should denote distinct objects) (6.4.5).
ja der Sinn ist mir klar, der Text aber nicht und die deutsche
Übersetzung machts auch nicht besser, kurzum ich verstehe es immer noch
nicht warum einer einem const char * einem variablen Inhalt zuweisen
will
Joachim B. schrieb:> ja der Sinn ist mir klar, der Text aber nicht und die deutsche> Übersetzung machts auch nicht besser, kurzum ich verstehe es immer noch> nicht warum einer einem const char * einem variablen Inhalt zuweisen> will
Kann ich leider nur mit einer Gegenfrage antworten: Warum sollte er
nicht? Eine Funktion mit (const char *) wird den String nicht verändern.
Also ist es zulässig, ihr ein Argument vom Typ (char *) zu übergeben.
Weshalb man möglichst alle Pointer-Parameter von Funktionen mit "const"
verzieren sollte, sofern das Objekt nicht verändert wird: Der Compiler
weiss dann, dass es nicht verändert wird, und kann auch ohne Kenntnis
des Inhalts der Funktion entsprechend optimieren.
A. K. schrieb:> Kann ich leider nur mit einer Gegenfrage antworten: Warum sollte er> nicht? Eine Funktion mit (const char *) wird den String nicht verändern.> Also ist es zulässig, ihr ein Argument vom Typ (char *) zu übergeben.>> Weshalb man möglichst alle Pointer-Parameter von Funktionen mit "const"> verzieren sollte: Der Compiler weiss dann, dass das Argument darin nicht> verändert wird, und kann entsprechend optimieren.
ich glaube mein Nebel lichtet sich so
1
const*charistjanurderPointeraufdieAdressevomchar*
aber für mein Verständnis war immer der String eine Konstante, OK der
Pointer kann auch konstant sein nur habe ich dann immer noch
Schwierigkeiten zu verstehen das ich deren Inhalt auf einen anderen *
char Pointer verändern kann...
ach ich gebs auf 30 Jahre C aber das werde ich nie kapieren.
const char * -- nicht-konstanter Pointer auf konstante chars
char * const -- konstanter Pointer auf nicht konstante chars
const * char -- Unfug
Die C Typedeklaration ist ein typisches Beispiel von "gut gemeint" aber
nicht "gut gemacht". Da stolpert anfangs jeder drüber. Nach 30 Jahren
sollte man das aber allmählich drauf haben.
A. K. schrieb:> const char * -- nicht-konstanter Pointer auf konstante charsA. K. schrieb:> Nach 30 Jahren> sollte man das aber allmählich drauf haben.
kann ja nix für meine Verständnisschwäche an dieser Stelle.
Joachim B. schrieb:> ja der Sinn ist mir klar, der Text aber nicht und die deutsche> Übersetzung machts auch nicht besser, kurzum ich verstehe es immer noch> nicht warum einer einem const char * einem variablen Inhalt zuweisen> will
Wenn ein Wert nicht verändert werden darf ist er konstant. Mit const
sagt man dem Compiler, das man etwas nicht verändern wird. Wenn etwas
nicht const ist, könnte man es verändern. In anderen worten: es spielt
für eine Funktion keine Rolle, wenn diese etwas bekommt das verändert
werden könnte, wenn diese daran nichts verändern wird. Innerhalb der
Funktion kann man dien Wert dann als konstant betrachten. Das gegenteil
trifft jedoch nicht zu. Erwartet eine Funktion einen Wert der nicht
const ist, könnte diese diesen verändern, deshalb kann man keinen Wert
übergeben der nicht verändert werden darf, also const ist, es sei denn
es wird eine Kopie davon angefertigt.
A.K schrieb
>const char * -- nicht-konstanter Pointer auf konstante chars>char * const -- konstanter Pointer auf nicht konstante chars
Dann müsste es ja noch
Stefan schrieb:> Dann müsste es ja noch> const char * const-- konstanter Pointer auf konstante chars>> geben.
So ist es auch.
> Das scheint irgendwie die Logic zu brechen.>> Ich hätte eher> const char const *>> vermuted.
Das wäre genauso wie
1
constchar*
und
1
charconst*
ein nicht konstanter Pointer auf ein konstantes char, nur doppelt
gemoppelt.
Hier noch einmal zur Verdeutlichung alle Möglichkeiten, wie die consts
auf die Deklaration verteilt werden können und wie sie jeweils zu lesen
sind:
Beispiel 1:
1
char*p;
bedeutet: p ergibt dereferenziert ein char.
Beispiel 2:
1
constchar*p;
bedeutet: p ergibt dereferenziert ein char, das konstant ist.
Beispiel 3:
1
charconst*p;
bedeutet: p ergibt dereferenziert eine Konstante, die vom Typ char ist.
Beispiel 4:
1
constcharconst*p;
bedeutet: p ergibt dereferenziert eine Konstante, die vom Typ char ist,
und dieses char ist konstant (doppelt gemoppelt).
Beispiel 5:
1
char*constp;
bedeutet: p ist konstant und ergibt dereferenziert ein char.
Beispiel 6:
1
constchar*constp;
bedeutet: p ist konstant und ergibt dereferenziert ein char, das
konstant ist.
Beispiel 7:
1
charconst*constp;
bedeutet: p ist konstant und ergibt dereferenziert eine Konstante, die
vom Typ char ist.
Beispiel 8:
1
constcharconst*constp;
bedeutet: p ist konstant und ergibt dereferenziert eine Konstante, die
vom Typ char ist, und dieses char ist konstant (doppelt gemoppelt).
Die Beispiele 2, 3 und 4 sind gleichwertig, ebenso die Beispiele 6,7 und
8.
Es kommt aber noch besser: Man darf nämlich die consts mehrmals
hintereinanderschreiben, ohne dass sich an ihrer Bedeutung etwas ändert.
Folgendes Beispiel wäre also mit den Beispielen 6, 7 und 8
gleichbedeutend:
Auch das ist einfach nur ein konstanter Pointer auf ein konstantes char.
Jetzt kommen sicher gleich der C-Hater und Paul Paumann hereingestürmt
mit den Worten "Ja, ja, C halt ..." ;-)
Yalu X. schrieb:> Jetzt kommen sicher gleich der C-Hater und Paul Paumann hereingestürmt> mit den Worten "Ja, ja, C halt ..." ;-)
ich mag ja eigentlich C aber an dieser Stelle hasse ich es!
Yalu X. schrieb:> Beispiel 6:> const char *const p;>> bedeutet: p ist konstant und ergibt dereferenziert ein char, das> konstant ist.>> Beispiel 7:> char const *const p;>> bedeutet: p ist konstant und ergibt dereferenziert eine Konstante, die> vom Typ char ist.
Ist beides das gleiche. Ich bevorzuge die letztere Schreibweise, da man
es dann von rechts nach links auflösen kann: "const pointer auf const
char". Ich glaube gelsen zu haben, dass die Erfinder zum "char const"
auch das "const char" unterstützen wollten, weil es sich besser lesen
läßt. Dieser Sonderfall Führt imho aber nur zur Verwirrung.
So jetzt kannst du mit Pointer auf Arrays weiter machen...
char const (*p)[42]... ;-)
Yalu X. schrieb:> Hier noch einmal zur Verdeutlichung alle Möglichkeiten, wie die consts> auf die Deklaration verteilt werden können und wie sie jeweils zu lesen> sind:>> Beispiel 1:>>
1
char*p;
>> bedeutet: p ergibt dereferenziert ein char.>> Beispiel 2:>>
1
constchar*p;
>> bedeutet: p ergibt dereferenziert ein char, das konstant ist.>> Beispiel 3:>>
1
charconst*p;
>> bedeutet: p ergibt dereferenziert eine Konstante, die vom Typ char ist.>> Beispiel 4:>>
1
constcharconst*p;
> ...
1) Mehrfaches Auftreten von "const" (auf der gleichen Seite vom "*") ist
redundant, d.h. alle "const" bis auf eines können gestrichen werden
falls sie auf der gleichen Seite vom "*" stehen.
2) Es ist wurscht ob man "const char" oder "char const" schreibt, ditto
für "volatile" und ander Qualifier.
Bitte reduzieren Sie die Anzahl der Zitatzeilen. Bitte reduzieren Sie
die Anzahl der Zitatzeilen. Bitte reduzieren Sie die Anzahl der
Zitatzeilen. Bitte reduzieren Sie die Anzahl der Zitatzeilen.
Wer sich über die seltsame Platzierung der Qualifier const/volatile ggf.
hinter dem * wundert: Im ursprünglichen C gab es keine Qualifier.
In C ist es per Definition aber egal, ob man
extern const int ...
oder irgendeine andere Permutation davon schreibt:
int const extern ...
Somit wird alles links vom * dem referenzierten Typ zugeschlagen,
weshalb
int const *
das gleiche ist wie
const int *
Damit ist klar, das "const" als Attribut des Pointers nicht links vom *
stehen kann, sondern nur rechts davon. Wenn man die C Syntax richtig
versteht.
Nicht jeder hat diese Logik freilich so richtig verstanden. Schon vor
ANSI C's const/volatile erfanden x86 Compiler eine Unterscheidung von
Pointern für die segmentierte Adressierung. Das hätte also für einen
segmentierten Pointer eigentlich
int * _far p;
heissen müssen. Leider hielten die Autoren solcher Compiler dies für
unzumutbar und definierten für ihre Compiler, dass
int _far * p;
ein segmentierter Pointer ist, obwohl es der Sprachlogik folgend
eigentlich eine segmentierte Integer wäre. Der Compiler musste sich
diesen Unfug wieder passend zurechtgebiegen.
Als dann ANSI C const/volatile einbrachte, ohne die Syntax so zu
vergewaltigen wie die x86 Compiler, war das Chaos perfekt. Denn nun
hatte man Qualifier vor und hinter dem *, weil sich in
int _far * const p;
sowohl _far als auch const in der Bedeutung eigentlich auf den Typ des
Pointers bezogen.
Das gleiche und in C++ auch gebräuchliche Problem entsteht auch bei
Arrays und Functions. Auch da müssen Qualifier, die sich nicht auf den
Return-Typ sondern die Funktion beziehen, hinter dem () platziert
werden:
int f() const;
Direkt davor, zwischen Name und []/() geht nicht, weil in der Typ-Syntax
von Casts keine Name enthalten ist.
Und dieses ganze Verwirrspiel entstand bloss deshalb, weil in grauer
Vorzeit jemand meinte, es wäre doch schön, wenn die Deklaration eines
Pointer wie dessen Verwendung aussähe.
Tom schrieb:> Es geht dem OP wahrscheinlich nicht darum, die Fehlermeldung irgendwie> wegzubekommen, sondern den dahinterliegenden potentiellen Fehler zu> beseitigen. Man kann auch die nervige Ölwarnleuchte am Auto überkleben.
Ja, aber den Fehler, der die Ölwarnleuchte zum aufleuchten bringt kann
man nicht beseitigen, indem man statt dem Auto mit dem Fehler einfach
ein anderes, bei dem sie nicht leuchtet, zur Werkstatt bringt.
A. K. schrieb:> Die C Typedeklaration ist ein typisches Beispiel von "gut gemeint" aber> nicht "gut gemacht". Da stolpert anfangs jeder drüber. Nach 30 Jahren> sollte man das aber allmählich drauf haben.
Optimal ist es nicht, aber die Regel ist nicht kompliziert. const
bezieht sich immer auf das, was links davon steht, außer wenn es ganz
links steht. Dann bezieht es sich auf das, was rechts davon steht. Die
meisten benutzen nur diese Ausnahme mit Abstand am häufigsten und
verstehen deshalb die Regel gar nicht.
char * const Regelfall, konstanter Zeiger auf nichtkonstanten char
char const * Regelfall, nichtkonstanter Zeiger auf konstanten char
const char * Ausnahmefall: das gleiche wie drüber
Und das läßt sich auch auf beliebig viele Pointer-Ebenen erweitern:
1
char**const*
ist ein nichtkonstanter Zeiger auf einen konstanten Zeiger auf einen
nichtkonstanten Zeiger auf einen nichtkonstanten char
Norbert schrieb:> Ich mach's mir etwas einfacher:> Ich will ein char.char> Ich will ein char und das soll const sein.char const> Ich will einen Zeiger auf char.char *> Ich will einen Zeiger auf ein char das const ist.char const *> Ich will einen Zeiger der const ist auf ein char.char * const> Ich will einen Zeiger der const ist auf ein char das const ist.char> const * const> Mehr brauch' ich glaube ich nicht!
Lies das ganze rückwärts, dann klingt es verständlicher:
Ich will ein char.
Rolf M. schrieb:> Optimal ist es nicht, aber die Regel ist nicht kompliziert. const> bezieht sich immer auf das, was links davon steht, außer wenn es ganz> links steht. Dann bezieht es sich auf das, was rechts davon steht.
const *p;
Rolf M. schrieb:> Norbert schrieb:>> Ich mach's mir etwas einfacher:>> ...>> ...>> ...>> Mehr brauch' ich glaube ich nicht!>> Lies das ganze rückwärts, dann klingt es verständlicher:
Danke für den Hinweis Rolf, aber ich komme mit meiner Interpretation
meiner eigenen Gedanken schon seit Jahrzehnten recht gut klar. ;-)
A. K. schrieb:> Rolf M. schrieb:>> Optimal ist es nicht, aber die Regel ist nicht kompliziert. const>> bezieht sich immer auf das, was links davon steht, außer wenn es ganz>> links steht. Dann bezieht es sich auf das, was rechts davon steht.>> const *p;
Gut, da kommt noch implizites int ins Spiel, was aber an der Stelle
hoffentlich keiner mehr nutzt. Mein gcc warnt da übrigens auch, sogar
per Default, ohne speziell hochgedrehtes Warnlevel.
In gewissem Sinne passt die Regel aber noch. Rechts vom const steht ein
implizites int, das nur nicht wirklich hingeschrieben wurde ;-)
Rolf Magnus schrieb:> Wenn du davon zuviel trinkst, werden die> Sterne immer mehr ;-)
kann hilfreich sein,
Sri Lanka '89 im Landesinneren, 5 Flaschen Arak für die Reisegruppe und
das Hotel hatte dann 5 *, die Kakalaken störten nicht mehr, der
Reiseleiter musste wiederbelebt werden :)
Yalu X. schrieb:> Jetzt kommen sicher gleich der C-Hater und Paul Paumann hereingestürmt> mit den Worten "Ja, ja, C halt ..." ;-)
Nein, Paul stürmt nicht mehr. Müller oder Schweinsteiger sind da
schneller und wendiger. Paul freut sich, daß ihn niemand zur Verwendung
einer solchen Piep (selbst zensiert) Sprache verpflichten kann. Er
lädt sich nämlich nicht ohne Not Sackgang und Verdruss auf.
;-)
MfG Paul