Gast
#2286098
Kann mir jemand den Unterschied zwischen char* a; char *a; erklären? Danke
|
Anzeige
|
Unterschied char* a; char *a;
Gast
#2286098
Kann mir jemand den Unterschied zwischen char* a; char *a; erklären? Danke Gibt keinen. Doch, gibt einen. Nicht für den Compiler, aber für den menschlichen Leser. Man ist als unbedarfter Mensch vielleicht geneigt, char* als Typ zu sehen (soweit richtig) und deshalb diese beiden zusammenzuschreiben. Tatsächlich bindet aber das * stärker an den folgenden Namen als an das char. Bei nur einem Variablennamen fällt das noch nicht unangenehm auf, aber bei mehreren:
Damit wird p1 vom Typ char* vereinbart, p2 dagegen vom Typ char! Gerade als Anfänger fällt man darauf leicht herein und unterstellen, daß beide char* wären. Deshalb kann man kaum zu dieser Schreibweise raten. So dagegen:
macht man deutlich, daß p1 und p3 vom Typ char* sind, p2 und p4 dagegen vom Typ char (auch wenn die Namen natürlich in einem echten Programm fragwürdig wären).
Gast
#2286202
Klaus Wachtler schrieb: > Doch, gibt einen. > > Nicht für den Compiler, aber für den menschlichen Leser. Hallo Klaus: Du bist hiermit der Gewinner der Woche in der Disziplin Haarespalten. Gratulation! Ach, stört mich nicht. In diesem Forum doch schon gar nicht :-) Im Ernst: bei so einer Gelegenheit darf man doch schon mal erwähnen, daß ein syntaktisch korrektes Programm noch nicht alles ist, oder nicht? Die Schreibweise
statt, wie bis dahin üblich,
stammt m.W. vom Herrn Stroustrup. Der Vorschlag war sicher gut gemeint, hat aber wohl mehr zur Ver- als Entwirrung unter den C++-Anfängern beigetragen.
Gast
#2286257
@ Klaus Wachtler Danke dass du es genau so erklärt hast, denn ich war fast schon der meinung, char* bezieht sich damit auf alles folgende. Danke :)
Gast
#2286272
Ich hätte noch eine Frage: <Datentyp> **<Name> Zeiger auf Zeiger auf <Datentyp> Das verstehe ich, da habe ich einen Zeiger, der auf einen anderen zeigen kann. <Datentyp> *<Name>[n] Feld aus n Zeigern auf <Datentyp> Hier habe ich ein Feld, voll mit Zeigern. <Datentyp> (*<Name>)[n] Zeiger auf Feld aus n <Datentyp>- Elementen Aber das verstehe ich nicht, und weiß nicht wie ich es anwenden soll. Ich habe einen Zeiger, der auf ein Feld mit n Elementen zeigt. Nur wie schreibe ich etwas in das Feld hinein? Danke
Gast
#2286283
Klaus Wachtler schrieb: > Im Ernst: bei so einer Gelegenheit darf man doch schon mal erwähnen, daß > ein syntaktisch korrektes Programm noch nicht alles ist, oder nicht? Richtig! Lesbarkeit ist ein wichtiges Kriterium der Softwarequalität!
Gast
#2286470
Das <Datentyp> (*<Name>)[n] ist doch das Selbe wie <Datentyp> *<Name>[n] da der * an den Namen gebunden ist. Der Zeiger auf Feld aus n <Datentyp>-Elementen ist dann <Datentyp> *(<Name>[n]) timo schrieb: > Ich habe einen Zeiger, der auf ein Feld mit n Elementen zeigt. > Nur wie schreibe ich etwas in das Feld hinein? Der Hintergrund der bescheuerten Deklarationssyntax von C ist der Versuch, die Deklaration wie die Verwendung aussehen zu lassen. Daher passt zur Deklaration int (*p)[10]; die Verwendung (*p)[i] DirkB schrieb: > <Datentyp> (*<Name>)[n] ist doch das Selbe wie > <Datentyp> *<Name>[n] > da der * an den Namen gebunden ist. Nein, denn [] bindet stärker als *.
Gast
#2287569
Klaus Wachtler schrieb: > Bei nur einem Variablennamen fällt das noch nicht unangenehm auf, aber > bei mehreren: > char* p1, > p2; > Damit wird p1 vom Typ char* vereinbart, p2 dagegen vom Typ char! > Gerade als Anfänger fällt man darauf leicht herein und unterstellen, daß > beide char* wären. > Deshalb kann man kaum zu dieser Schreibweise raten. Richtig. Man schreibt es besser so:
dann erübrigt sich die ganze Fragestellung. Yalu X. schrieb: > Die Schreibweise > char* a; > > statt, wie bis dahin üblich, > char *a; > > stammt m.W. vom Herrn Stroustrup. Manchmal wird auch eine dritte Schreibweise verwendet:
> Der Vorschlag war sicher gut gemeint, hat aber wohl mehr zur Ver- als > Entwirrung unter den C++-Anfängern beigetragen. Ich kenne eigentlich keinen Fall, wo jemand dadurch verwirrt wurde und finde die Originalschreibweise deutlich verwirrender, weil das *, obwohl es Teil des Typs ist, am Namen statt am Typ hängt. Wie Kernighan und Ritchie darauf gekommen sind, daß das dahingehören könnte, ist mir immer noch ein Rätsel. Ich kenne zwar den Gedankengang, aber finde ihn unsinnig. timo schrieb: > <Datentyp> (*<Name>)[n] Zeiger auf Feld aus n <Datentyp>- > Elementen > > Aber das verstehe ich nicht, und weiß nicht wie ich es anwenden soll. > > Ich habe einen Zeiger, der auf ein Feld mit n Elementen zeigt. Ja. Das ist zwar eher unüblich, aber möglich. > Nur wie schreibe ich etwas in das Feld hinein? (*<Name>)[n] = x; Rolf Magnus schrieb: > Ich kenne eigentlich keinen Fall, wo jemand dadurch verwirrt wurde Ich schon. Hier ist z.B. einer: timo schrieb: > Danke dass du es genau so erklärt hast, denn ich war fast schon der > meinung, char* bezieht sich damit auf alles folgende. ;-) Rolf Magnus schrieb: > und finde die Originalschreibweise deutlich verwirrender, weil das *, > obwohl es Teil des Typs ist, am Namen statt am Typ hängt. Ja, die C-Deklarationen sind teilweise schon etwas gewöhnungsbedürftig. Wenn man das Prinzip aber erst einmal durchschaut hat, sind sie gerade bei komplizierteren Datentypen oft etwas leichter lesebar. Beispiel:
Packte man alles Typzugehörige zusammen und an den Anfang, sähe es so aus:
Ich finde nicht, dass das übersichtlicher ist. Oder wie sähe deiner Meinung nach die lesbarste Deklaration eines Funktionspointers aus? Die zweite Schreibweise (int(*)(int)) taucht allerding bei Cast-Opera- tionen auf, was aus Gründen der Einheitlichkeit dafür sprechen würde, sie auch für Deklarationen zu verwenden. Der Fehler in C ist, dass * ein Präfix-Operator ist, die übrigen Operatoren dieser Klasse aber Postfix-Operatoren sind, wie (), [] und ".". Daraus folgt direkt der ganze überflüssige Rattenschwanz mit Vorrangstufen, Klammern usw, der Deklaration und Verwendung so bizarr macht. Mit Dereferenzierung dahinter statt davor löst sich vieles in der Deklaration in Luft auf, auch die Verwendung wird einfacher. Aus (*p).a aka p->a wird p*.a. Keine spezieller Operator nötig. Array aus Pointern: p[]* statt *p[] Pointer auf Array: p*[] statt (*p)[] usw. Dann könnte man noch den Schwachfug eliminieren, den Typnamen als einleitendes Schlüsselwort für Variablendeklarationen einzuspannen, was eine Kopplung von Scanner und Parser erzwingt, weil der Scanner einen Typnamen kontextabhängig mal als normalen Namen und mal als Typnamen klassifizieren muss. Also vorneweg die nun obligatorische Storage Class, dann der Name, die Typenkette endend mit dem Basistyp. Ergäbe dann auto p[10]* int; Einfach von links nach rechts gehen und es liest sich als genau das, was man verbal auch so ausdrücken würde, nämlich dass "p" ein Array aus Pointern auf "int" ist. Nicht wie bisher vom u.U. nicht vorhandenen Namen (beim cast) unter Beachtung des Vorrangs mal links mal rechts nach aussen. Nebenbei wäre C++ so eine der Zweideutigkeiten erspart geblieben, denn sowas wie typename(a); lässt sich nur durch künstliche Festlegung aufdröseln, weils syntaktisch sowohl eine Deklaration von "a" mit überflüssigen Klammern als auch Aufruf von Konvertierungsfunktion/Konstruktur sein kann. Wer meint, das liesse sich ja durch die Klammer erkennen: Erstens ändert das nichts am Problem des Parsers, zweitens dürfte sich auch ein Beispiel konstruieren lassen, dass in beiden Fällen nichts Überflüssiges enthält. Hört sich plausibel an. Nur leider etwas zu spät :-) A. K. schrieb: > Mit Dereferenzierung hinter > den Namen löst sich vieles in der Deklaration in Luft auf, auch die > Verwendung wird einfacher. Gute Idee. Ganz nebenbei würde man dadurch auch den Fehler in
vermeiden. Wäre die Postfixdereferenzierung wirklich perfekt, oder entstehen dadurch vielleicht andere Nachteile? Yalu X. schrieb: > Gute Idee. Ganz nebenbei würde man dadurch auch den Fehler in > a = b/*pc; schick, das hatte ich noch gar nicht auf dem Schirm. Yalu X. schrieb: > A. K. schrieb: >> Mit Dereferenzierung hinter >> den Namen löst sich vieles in der Deklaration in Luft auf, auch die >> Verwendung wird einfacher. > > Gute Idee. Ganz nebenbei würde man dadurch auch den Fehler in > >
> > vermeiden. > > Wäre die Postfixdereferenzierung wirklich perfekt, oder entstehen > dadurch vielleicht andere Nachteile? Naja andersherm dann ;)
Yalu X. schrieb: > Wäre die Postfixdereferenzierung wirklich perfekt, oder entstehen > dadurch vielleicht andere Nachteile? Ich habs nie implementiert und auch nicht komplett durchdacht, bin mir daher nicht völlig sicher. Man müsste beispielsweise Casts unter die Lupe nehmen, wie die sich dann elegant darstellen lassen. Stefan B. schrieb: > Naja andersherm dann ;) Das ist ein Fehler in der Definition des Kommentarsymbols, nicht von "*". Das // in C++ kann in keinem anderen Kontext vorkommen. Besser wäre beispielsweise /. xxx ./ gewesen. Stefan B. schrieb: > Naja andersherm dann ;)a= pc*/b Das wäre nicht so schlimm. Das Kommentarendezeichen */ ist kein Scanner- Token, da das Herausfiltern der Kommentare vor der lexikalischen Analyse (sogar schon vor dem Preprocessing) stattfindet.
Gast
#2287690
>Wäre die Postfixdereferenzierung wirklich perfekt, oder entstehen >dadurch vielleicht andere Nachteile? Diese gefällt mir zumindest besser, und ich finde sie verständlicher, als bei C. Ich kenne sie beruflich beim Programmieren von SPS in der Sprache ST: Dort sieht das so aus:
Yalu X. schrieb: > Das wäre nicht so schlimm. Das Kommentarendezeichen */ ist kein Scanner- > Token, da das Herausfiltern der Kommentare vor der lexikalischen Analyse > (sogar schon vor dem Preprocessing) stattfindet. Ändert nichts am Problem:
Gast
#2287735
Wieder mal ein typischer mikrocontroller.net Tread. Er ist wieder mal entgleist. Die ursprüngliche Frage war, was der Unterschied ist zwischen char* ichBinEinZeiger und char *ichBinEinZeiger Die Antwort ist: Es ist dasselbe, eine Frage des persönlichen Geschmacks. Damit ist es im Sinne des Fragestellers beantwortet. Ende und gut. Kein weiteres gequatsche um des Kaisers Bart. Gerade Anfänger können diesen sinnlosen Mist, der immer wieder hinterherkommt nicht einordnen. Sonst würden sie ja keine Frage stellen. Also was soll das Ganze? Wenn ihr zuviel Freizeit habt, könnt ihr bei mir den Rasen mähen oder euch sonstwie nützlich machen. Markus G. schrieb: > Damit ist es im Sinne des Fragestellers beantwortet. Ende und gut. Kein > weiteres gequatsche um des Kaisers Bart. Webforen sind keine Support-Hotlines, bei denen mit der Beantwortung des Falles dieser geschlossen wird. Sondern sind Diskussionsforen. Rasen mähen um Mitternacht? Deine Nachbarn würden sich freuen.
Gast
#2287748
A. K. schrieb: > Webforen sind keine Support-Hotlines, bei denen mit der Beantwortung des > Falles dieser geschlossen wird. Sondern sind Diskussionsforen. Deswegen kann man doch eine offensichtliche Anfängerfrage beantworten, ohne eine Diskussion über die grundsätzliche Vorgehensweise eines Compilers loszutreten. Damit ist ihm nicht geholfen.
Gast
#2287756
A. K. schrieb: > Rasen mähen um Mitternacht? Deine Nachbarn würden sich freuen. Mein Nachbar ist Bademeister bei uns im Freibad und mäht seinen Rasen gewöhlich am Samstag bevor er zur Arbeit geht. Das Freibad öffnet um 8:00 Uhr. Das ist für mich auch nicht immer lustig.
Gast
#2287757
nur mal so in den Raum geworfen (weil ich persönlich das echt toll finde ^_^): In D gibt es einen unterschied. ACHTUNG: NICHT IN C / C++ schreibt man: int* p1, p2, p3; sind alle drei Zeiger. schreibt man aber: int *p1, p2, p3; ist nur p1 ein Zeiger. Markus G. schrieb: > Deswegen kann man doch eine offensichtliche Anfängerfrage beantworten, War doch mit den ersten 2 Antworten schon geschehen.
Gast
#2287818
Yalu X. schrieb: > Packte man alles Typzugehörige zusammen und an den Anfang, sähe es so > aus: > int(*)(int) fptr; > > Ich finde nicht, dass das übersichtlicher ist. Ich finde es gar nicht so schlecht. Da ist der Name zumindest nicht irgendwo mitten reingefummelt, sondern wie bei einfacheren Variablendefinitionen rechts vom Typ, schön separat und gleich erkennbar. Aber Deklarationen, die einen Funktionszeiger beinhalten, sind in C sowieso furchtbar. Man schaue sich die Deklaration der Standard-Funktion signal() an, die einen Funktionszeiger übergeben bekommt und einen zurückgibt:
Ein munterer Mix aus Prefixen, Postfixen und irgendwo dazwischen noch Funktionsname und Parameternamen. Wenn man das alles etwas sortieren würde, wäre das meiner Meinung nach schon besser zu lesen:
> Die zweite Schreibweise (int(*)(int)) taucht allerding bei Cast-Opera- > tionen auf, was aus Gründen der Einheitlichkeit dafür sprechen würde, > sie auch für Deklarationen zu verwenden. Das außerdem. Markus G. schrieb: > A. K. schrieb: >> Webforen sind keine Support-Hotlines, bei denen mit der Beantwortung des >> Falles dieser geschlossen wird. Sondern sind Diskussionsforen. > > Deswegen kann man doch eine offensichtliche Anfängerfrage beantworten, > ohne eine Diskussion über die grundsätzliche Vorgehensweise eines > Compilers loszutreten. Damit ist ihm nicht geholfen. Die Frage wurde beantwortet, also ist ihm geholfen. Wem ist denn geholfen, wenn die Diskussion an dieser Stelle sofort abgebrochen wird? Markus G. schrieb: > A. K. schrieb: >> Rasen mähen um Mitternacht? Deine Nachbarn würden sich freuen. > > Mein Nachbar ist Bademeister bei uns im Freibad und mäht seinen Rasen > gewöhlich am Samstag bevor er zur Arbeit geht. Das Freibad öffnet um > 8:00 Uhr. Das ist für mich auch nicht immer lustig. Könnten wir bitte beim Thema bleiben? :-) Rolf Magnus schrieb: >> int(*)(int) fptr; >> >> Ich finde nicht, dass das übersichtlicher ist. > > Ich finde es gar nicht so schlecht. Da ist der Name zumindest nicht > irgendwo mitten reingefummelt, sondern wie bei einfacheren > Variablendefinitionen rechts vom Typ, schön separat und gleich > erkennbar. Diese Variante wird man reflexhaft von recht nach links lesen, und dann suggeriert sie eine Funktion, die einen Pointer auf int retourniert. Man muss also auch hier immer noch Stricken spielen, eine links, eine rechts, eine fallen lassen. Nein, aus der Nummer kommt man nicht raus. Mit einem Mix aus Prefix und Postfix (eigentlich Infix) muss man innen anfangen und sich nach aussen durchkämpfen. Und grad die Cast Notation erschwert es auch noch zusätzlich, dieses "innen" überhaupt zu finden. A. K. schrieb: > Ändert nichts am Problem:/* > dieser = code+ist*/deaktiviert; > */ Klar, das ergibt einen Fehler. Der Fehler entsteht man aber auch dann, wenn der auskommentierte Codeabschnitt bereits /**/-Kommentare enthält. Insofern hat man mit dem Postfix-* nicht viel verloren. Die bessere Methode zum "Auskommentieren" ist ohnehin #if 0 ... #endif, auch wenn es etwas mehr Tipparbeit ist. Markus G. schrieb: > Wieder mal ein typischer mikrocontroller.net Tread. Er ist wieder mal > entgleist. Von Entgleisung würde ich hier nicht sprechen, sondern eher von einer Themenerweiterung. Nachdem Stefan Ernst bereits nach 3 Minuten die knackig-korrekte Antwort gegeben hat, nämlich > Gibt keinen. ist es in einem Forum wie diesem durchaus legitim, anschließend noch etwas ins Detail zu gehen und auch Hintergründe zu beleuchten. Wen nur die Antwort auf die Frage interessiert, hört danach einfach auf zu lesen. Von der speziellen Frage "Unterschied char* a; char *a;" zur etwas allgemeineren Frage der Platzierung des Dereferenzierungssym- bols ist ja auch kein wirklich großer Sprung. Antwort schreibenBitte melde dich an, um einen Beitrag zu schreiben. |
Anzeige
|