mikrocontroller.net

Forum: Compiler & IDEs pointer auf const


Autor: Timm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

sind folgende 2 Ausdrücke die gleichen?

// ptr ist ein Pointer auf ein konstantes void
const void  * ptr

void const * ptr


Das untere ist etwas schöner zu lesen, denke ich.

Gruß!

Autor: NurSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein,

Das eine ist ein konstanter Pointer auf sich Void Daten, die sich ändern 
können
Das andere ist ein änderbarer Pointer, der auf konstante Void Daten 
zeigt.

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein, ein konstanter pointer auf void Daten wäre

void * const ptr

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Timm schrieb:

Hier hilft http://cdecl.org/

> const void  * p

declare p as pointer to const void

> void const * p

syntax error

> void * const p

declare p as const pointer to void

Autor: Timm (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark Brandis schrieb:
>> void const * p
>
> syntax error


das kann ich nicht bestätigen. Mit meinem Compiler ist diese Reihenfolge 
egal.

Wichtig ist nur was vor und was nach dem Stern steht.

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es empfiehlt sich auch die zweite Schreibweise. Warum? Beispiel dazu:

typedef char* CHARS;
1> typedef CHARS const CPTR;

im Gegensatz zu

2> typedef const CHARS CPTR;

Wenn man CHARS ersetzt, sieht man den Unterschied:

1> typedef char* const CPTR;

2> typedef const char* CPTR;

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas K. schrieb:

> Wenn man CHARS ersetzt, sieht man den Unterschied:

typedef ist keine Textersetzung.

Autor: NurSo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas K. schrieb:
> Nein, ein konstanter pointer auf void Daten wäre
>
> void * const ptr

Wenn er Recht hat, hat er Recht.
Sorry, sollte wohl genauer hinschauen.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mark Brandis schrieb:

>> void const * p
>
> syntax error

Ist aber korrektes C. Die Reihenfolge der declaration-specifier ist 
nicht vorgeschrieben. So ist statt
   extern const int var;
ebenso zulässig:
   int const extern var;

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas K. schrieb:
> Es empfiehlt sich auch die zweite Schreibweise.

Das ist ein etwas an den Haaren herbeigezogenes Argument
denn in deinem Beispiel ist es auf jeden Fall immer der Pointer der 
konstant ist.

Man kann nämlich auch als Fautregel angeben:
Grundsätzlich empfiehlt es sich, einen Pointer Datentyp nicht in einem 
typedef zu verstecken (und auf keinen Fall in einem Makro!). Das gibt 
auf lange Sicht gesehen nämlich meistens Ärger und Verwirrung.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Grundsätzlich empfiehlt es sich, einen Pointer Datentyp nicht in einem
> typedef zu verstecken

Warum? Das sehe ich durchaus anders. Es wäre aber schon praktisch, wenn 
man dem Namen ansieht, dass es sich um einen Pointer handelt.

> (und auf keinen Fall in einem Makro!)

D'accord.

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Thomas K. schrieb:
>
>> Wenn man CHARS ersetzt, sieht man den Unterschied:
>
> typedef ist keine Textersetzung.

Habe ich nie behauptet. Die Aussage war im Sinne von "wenn man das ganze 
ohne den typedef direkt mit den Typen schreibt"

Karl heinz Buchegger schrieb:
> Das ist ein etwas an den Haaren herbeigezogenes Argument
> denn in deinem Beispiel ist es auf jeden Fall immer der Pointer der
> konstant ist.

falsch, denn 1> ist ein konstanter pointer to char und 2> ist ein 
pointer zu einem konstanten char. Somit ist bei 2> nicht der pointer 
konstant.

Das Beispiel soll nur das Problem verdeutlichen. Bei dem hier genannten 
Beispiel ist dies irrelevant, aber typedefs werden u.a. bei Templates 
immer oft und gerne genutzt und dort kann das von mir genannte deutliche 
Unterschiede machen.

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb im Beitrag #1791567:
> Thomas K. schrieb:
>
>> Habe ich nie behauptet. Die Aussage war im Sinne von "wenn man das ganze
>> ohne den typedef direkt mit den Typen schreibt"
>
> Stand so nicht da. Das war dort stand war schlicht falsch.

Es steht unverändert oben und wenn man sich nur den Teilsatz anstatt dem 
ganzen Satz ansieht, kann man sich das natürlich sonstwie hin 
interpretieren. "Wenn man CHARS ersetzt" sagt mit keinem Wort aus, dass 
das typedef eine Textersetzung wäre. Aber man kann natürlich alles immer 
so lesen und verstehen, dass man was zum meckern hat...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Thomas K. schrieb:
> A. K. schrieb:
>> Thomas K. schrieb:

>> Das ist ein etwas an den Haaren herbeigezogenes Argument
>> denn in deinem Beispiel ist es auf jeden Fall immer der Pointer der
>> konstant ist.
>
> falsch, denn 1> ist ein konstanter pointer to char und 2> ist ein
> pointer zu einem konstanten char. Somit ist bei 2> nicht der pointer
> konstant.

Hmm
Der Compiler sieht die Sache aber anders
#include <stdio.h>
#include <stdlib.h>


typedef char* CHARS;
typedef const CHARS cptr_1;
typedef CHARS const cptr_2;

int main()
{
  cptr_1 ptr1 = "Hallo";
  cptr_2 ptr2 = "World";
  
  ptr1 = "Juhu";    // <----
  ptr2 = "Kukuck";  // <----
  
  *ptr1 = 'A';
  *ptr2 = 'B';
}

Beide Zuweisungen an die Pointer werden mit
"error C2166: l-value specifies const object"
quittiert.

Die Character darf ich allerdings in beiden Fällen ändern :-)

Fazit: In beiden Schreibweisen ist es der Pointer der konstant ist. 
Siehe es so - der typedef legt um den Datentyp so etwas ähnliches wie 
eine gedankliche Klammer. CHARS ist in erster Linie ein 
Pointer-Datentyp. jegliche Modifier wirken daher auf den Pointer.

Wie weiter oben schon gesagt wurde: typedef macht keine Textersetzungen! 
Sobald du daher versuchst das Verhalten mit Textersetzung zu erklären, 
kannst du Schiffbruch erleiden.

zb sind in
typedef char * CHARS;
CHARS  i, j, k, l;

alle Variablen i, j, k und l vom Datentyp Pointer to char.

während in
#define CHARS char *
CHARS i, j, k, l;

genauso wie in
char * i, j, k, l;

nur i ein Pointer ist und j, k und l normale char sind.


A.K. siehst du jetzt, warum ein typedef für einen Pointer oft keine gute 
Idee ist. Wie ich schon sagte: führt oft auf lange Sicht zu Ärger und 
Verwirrung.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> A.K. siehst du jetzt, warum ein typedef für einen Pointer oft keine gute
> Idee ist.

Für mich entstand hier kein bischen Verwirrung, aber ich erkenne, dass 
andere dadurch offensichtlich verwirrt werden.

Übrigens ist die Schreibweise mit "const" hinter dem Typ in C++ üblich 
denn man findet sie regelmässig bei Referenzen, z.B. "int const& x".

> Wie ich schon sagte: führt oft auf lange Sicht zu Ärger und
> Verwirrung.

Was dagegen mich früher verwirrte, war die Schreibweise
   int far *p; //1
statt
   int *far p; //2
denn aus syntaktischer Sicht ist (1) blühender Unsinn, gehört das "far" 
doch eigentlich logisch zum Pointer. Es kann in dieser Form aber 
aufgrund der syntaktischen Struktur unmöglich dem "*" sondern nur dem 
"int" zugeordnet werden. Da hatte jemand wohl krampfig versucht, es für 
Leuten mit weniger Einblick in die syntaktische Struktur lesbarer zu 
machen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:

> Für mich entstand hier kein bischen Verwirrung, aber ich erkenne, dass
> andere dadurch offensichtlich verwirrt werden.

Yep.

Und ja: Ich hatte auch eine Phase, in der ein
typedef struct
{
  int irgendwas;
  char was_anderes;
}
my_struct;
typedef my_struct * my_struct_ptr;

ganz normal war, wie wahrscheinlich bei vielen anderen auch. Habs aber 
dann wieder aufgegeben. Es stand einfach nicht dafür. Der * in der 
Deklaration leuchtet aus irgendeinem Grund besser aus dem Monitor 
heraus, als es jegliche _ptr oder _Ptr oder wie auch immer Anhängsel je 
könnten. Ich gesteh aber gerne zu, dass das hauptsächlich Gewohnheit 
ist.

> Was dagegen mich früher verwirrte, war die Schreibweise
>    int far *p;
> denn aus syntaktischer Sicht ist das blühender Unsinn, gehört das "far"
> doch eigentlich zum Pointer. Es kann in dieser Forme aber aufgrund der
> syntaktischen Struktur nicht dem "*" sondern nur dem "int" zugeordnet
> werden.

Yep.
Der Kelch ist Gottseidank an mir vorbei gegangen.
Wir sind gerade von MS-C auf Watcom-C gewechselt, als die far Pointer 
bei MS essentiell wurden. Und in Watcom-C war das kein Thema.

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grundsätzlich kann man sagen:

Ein const bezieht sich immer auf den Typ, der unmittelbar links davon 
steht. Steht da nichts, dann bezieht es sich auf das, was unmittelbar 
rechts davon steht.


Gruss
Simon

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dadurch dass in der Deklaration die Qualifier, Type und Storage Class 
keine bestimmte Reihenfolge einhalten müssen, ist übrigens auch sowas 
erlaubt:
int typedef const foo;

"typedef" zählt syntaktisch in C als storage-class-specifier, auch wenn 
es semantisch nichts mit der Storage Class zu tun hat.

Allerdings gehört das wohl auch zu den Dingen, die man sich im Sinne der 
Lesbarkeit des Codes eher verkneifen sollte.

Andreas

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> genauso wie in
>
> char * i, j, k, l;
>
> nur i ein Pointer ist und j, k und l normale char sind.

Noch etwas weitergehend ist auch in
char * const i, j, k, l;

nur i konstant, während j, k und l veränderbar sind.

Andreas

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was ich skuril finde:

Bei
  int const i = 0, j = 0;
sind sowohl i als auch j const.

Dagegen bei
  int * const i = 0, j = 0;
ebenso wie bei
  int const * i = 0, j = 0;
ist nur i const, j nicht.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> ebenso wie bei
> int const * i = 0, j = 0;
> ist nur i const, j nicht.

Nein, in letzterem Fall ist j const, i nicht (aber *i).

Andreas

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
sorry, stimmt natürlich.
Aber trotzdem nicht schön gelöst in C.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:

>
> int typedef const foo;
> 
>

Ich dachte bisher, im Prä-C99 überrascht mich nichts mehr.
Aber das hier ... :-)

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> sorry, stimmt natürlich.
> Aber trotzdem nicht schön gelöst in C.


Seh' ich auch so. Bezüglich const macht die C-Syntax ein bisschen ein 
Bordell. Wenn man const grundsätzlich dem, was "verkonstet" werden soll, 
nachstellt, wird's einigermassen einheitlich:

Aber

int const i=0

sieht halt bescheiden aus (wenn's auch korrekt ist).

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aber grundsätzlich ist die oben genannte Regel sehr gut geeignet, das 
Bordell mit den const zu durchschauen:


Klaus Wachtler schrieb:
> Was ich skuril finde:
>
> Bei
>
>   int const i = 0, j = 0;
> 
> sind sowohl i als auch j const.
>

links von const ist ein int. also werden zwei konstante ints deklariert.

> Dagegen bei
>
>   int * const i = 0, j = 0;
> 

links von const ist ein int*. Also werden zwei konstante Pointer auf 
(variable) ints deklariert.

> ebenso wie bei
>
>   int const * i = 0, j = 0;
> 
> ist nur i const, j nicht.

hier ist eben links von const wieder nur ein int. Also werden zwei 
konstante ints deklariert. Einer, der 'nen Pointer namens i drauf hat, 
und einen namens j.
int const * const i

deklariert jetzt dementsprechend einen konstanten Pointer auf eine 
Konstante

Doof ist jetzt einfach, dass die Regel etwas lasch ist, und dass const 
eben auch links stehen kann statt rechts (wobei es aber immer erst nach 
links "schaut"). Und dummerweise wird gerade im allerallerersten Fall, 
der in den Lehrbüchern steht, von dieser Ausnahmeregelung gebrauch 
gemacht.
const int i=0;

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon Huwyler schrieb:
>>   int * const i = 0, j = 0;
>>
> links von const ist ein int*. Also werden zwei konstante Pointer auf
> (variable) ints deklariert.

Und prompt in die Falle getappt ;-) j ist hier ein einfacher int, es ist 
weder ein Pointer noch const.

Simon Huwyler schrieb:
> Seh' ich auch so. Bezüglich const macht die C-Syntax ein bisschen ein
> Bordell. Wenn man const grundsätzlich dem, was "verkonstet" werden soll,
> nachstellt, wird's einigermassen einheitlich:

Eigentlich muss man sich nur eins klar machen: alles ab einschliesslich 
dem "*" gehört nicht mehr zu den "declaration-specifiers", sondern ist 
Teil des "declarator". Deshalb wird das dann auch nicht in einer 
Deklaration von mehreren Variablen an die anderen in der Liste 
"weitergereicht". Damit bezieht sich ein const vor dem ersten "*" auf 
alle Variablen in der Liste, ein const zwischen "*" und Identifier 
dagegen nur auf die einzelne.

Der Knackpunkt an der Sache, der diese Syntax-"Verrenkungen" nötig 
macht, ist der, dass bei einer Pointer-Deklaration wenn man so will 
zwei Objekte auf einmal deklariert werden, erstens der Pointer selbst 
und zweitens das Ziel dieses Pointers. Die "Trennstelle" zwischen den 
Teilen ist im Programmcode das "*"-Zeichen.

Exakt genauso verhält es sich auch bei Array- oder 
Funktionsdeklarationen, allerdings ist das identische Verhalten da ein 
wenig intuitiver:
const int i[10], j(int), k;

Hier ist i ein Array (von konstanten ints), j eine Funktion mit einem 
int-Parameter und einem const int als Rückgabewert, und k ein einzelner 
konstanter int.

Zur Erhöhung der Lesbarkeit ist es aber meist empfehlenswert, 
Deklarationen nur dann zusammenzuziehen, wenn diese auch wirklich im 
Ergebnis gleich sind:
const int i1, i2;
const int *p1, *p2;

und /nicht/:
const int i1, i2, *p1, *p2;

Ein "Trost" ist vielleicht auch noch, dass konstante Pointer tendenziell 
eher selten anzutreffen sind (wenn dann meist nur als 
Funktionsparameter), konstante Pointer- Ziele sind wesentlich 
häufiger.

Andreas

Autor: Simon Huwyler (simi)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:
> Simon Huwyler schrieb:
>>>   int * const i = 0, j = 0;
>>>
>> links von const ist ein int*. Also werden zwei konstante Pointer auf
>> (variable) ints deklariert.
>
> Und prompt in die Falle getappt ;-) j ist hier ein einfacher int, es ist
> weder ein Pointer noch const.



grrrrrrrrrrrrrrrrrrrrrr.... verdammmt! Hast natürlich recht!

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Deklarationssyntax von C war von Anfang an eine Fehlkonstruktion. 
Die ursprüngliche Idee dahinter, die Deklarationssyntax wie die 
Verwendung aussehen zu lassen, hat zu einer katastrophalen Syntax 
geführt, die in diesem Leben wohl leider nicht zu retten ist.

Eigentlich sollte es die Sache vereinfachen. Praktisch führt es dazu, 
dass Mensch ähnlich wie ein maschineller Parser entlang der formalen 
Sprachstrukturen unter Berücksichtigung von der operator precedences das 
Statement analysieren muss. Mag also sein, dass jemand, der sich bereits 
auf dieser Ebene näher mit C befasst hat, es beim Verständnis davon 
etwas leichter hat.

Wenn man das mit der blitzsauberen Methodik der Wirth'schen 
Sprachfamilie vergleicht, in denen in schlichter linearer Weise von 
links nach rechts hingeschrieben wird, was man meint...

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt.

Aber letztlich muß man sich nicht damit herumplagen.
Ich bin halt feige und nehme im Zweifel ein paar mehr Deklarationen:
  const int *i;
  int        j;
  ....

Insofern ist es unschön gemacht, aber leicht zu umgehen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Die Deklarationssyntax von C war von Anfang an eine Fehlkonstruktion.
> Die ursprüngliche Idee dahinter, die Deklarationssyntax wie die
> Verwendung aussehen zu lassen, hat zu einer katastrophalen Syntax
> geführt, die in diesem Leben wohl leider nicht zu retten ist.

Und ich dachte schon, ich bin der Einzige der für derart ketzerische und 
unkeusche Gedanken auf den Scheiterhaufen kommen wird.

> Ich bin halt feige und nehme im Zweifel ein paar mehr Deklarationen

Mach ich auch so.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Und ich dachte schon, ich bin der Einzige der für derart ketzerische und
> unkeusche Gedanken auf den Scheiterhaufen kommen wird.

Ich hatte das Vergnügen, einen K&R-Parser in yacc die ANSI-Syntax 
beizubringen. Da bringt einem solche Spässe manchmal näher als einem 
lieb ist. Und es schärft den Sinn für syntaktische Aspekte. So hatte 
Stroustrup mit C++ leider die K&R-Tradition der syntaktischen 
Stolpersteine nahtlos fortgesetzt. Ich erinnere mich noch gut dran, wie 
mir bei der Lektüre seines Buches die Haare zu Berge standen.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Andreas Ferber schrieb:
>
>>
>> int typedef const foo;
>> 
>>
>
> Ich dachte bisher, im Prä-C99 überrascht mich nichts mehr.
> Aber das hier ... :-)

Fällt wohl in die gleiche Kategorie wie sowas:
int foo[20];

int
getfoo(int i)
{
  return i[foo];
}

Autor: Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jörg Wunsch schrieb:
> Fällt wohl in die gleiche Kategorie wie sowas:
> int foo[20];
>
> int
> getfoo(int i)
> {
>   return i[foo];
> }

Und dabei meckert der Compiler nicht, wenn man einen [] auf einen 
nicht-Array und nicht-Pointer-Typ loslässt? =-O

Autor: Mark Brandis (markbrandis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
foo[] ist ein Array. Auch wenn es hier so aussieht als ob i das Array 
wäre :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:

> Und dabei meckert der Compiler nicht, wenn man einen [] auf einen
> nicht-Array und nicht-Pointer-Typ loslässt? =-O

Nö.

  a[i]  <==>  *( a + i )  <==>  *( i + a )  <==>  i[a]

So wie Arrayindizierung in C definiert ist, ist das eine logische 
Konsequenz. Der Compiler muss   a[i]  zuallererst in *( a + i ) 
umformen. Alles andere folgt dann.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus schrieb:
> Und dabei meckert der Compiler nicht, wenn man einen [] auf einen
> nicht-Array und nicht-Pointer-Typ loslässt? =-O

Schau dir die Definition des Operators im Standard an. Das hängt mit der 
Definition von Arrayzugriffen auf dem Weg über Pointerarithmetik 
zusammen.

Das Subskripting in dem Beispiel ist per Definition im Standard 
identisch zu:
return *(i+foo);

Aufgrund der Kommutativität des +-Operators ist das wiederum identisch 
zu
return *(foo+i);

und das wiederum zu
return foo[i];

Das einzig relevante ist, dass bei der Addition irgendetwas rauskommt, 
was mit dem *-Operator dereferenziert werden kann.

Andreas

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da passt diese Referenz eigentlich ganz gut mal wieder hin. ;-)

http://www.gnu.org/fun/jokes/unix-hoax.html

Autor: Yalu X. (yalu) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:
> return *(i+foo);
>
> Aufgrund der Kommutativität des +-Operators ist das wiederum identisch
> zu
> return *(foo+i);

Hier liegt IMHO der Hund für die Verwirrung bei der Arrayindizierung
begraben. Da bei der Pointeraddition zwei völlig unterschiedliche
Datentypen miteinander verknüpft werden, erwartet man hier nicht
unbedingt Kommutativität. Ich würde nicht einmal erwarten, dass die
Operation Integer+Pointer überhaupt definiert ist. Wäre sie es nicht,
wäre es Integer[Pointer] ebenfalls nicht, und die Verwirrung würde gar
nicht erst entstehen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man hätte aber auch ganz einfach fordern können, dass bei

a[i]

das a entweder ein Array oder ein Pointer Typ sein muss. Und zwar noch 
ehe man die Konversion nach *(a+i) macht.

Aber dann wären wieder 0.0005% aller C-Programme (OK, im OCCC wären es 
mehr gewesen) nicht mehr kompatibel gewesen und 2 von 5 Millionen 
C-Programmierer hätten aufgeheult, weil sie ihr geliebtes

    digit = i["0123456789"];

nicht mehr benutzen können.


Das K&R diese Forderung nicht erhoben haben, kann ich noch verstehen. 
Aber das das C-Kommitee da nicht irgendwann einmal selbst über den 
eigenen Schatten springt und die vielbeschworene "Abwärtskompatibilität, 
koste es was es wolle und egal wie unsinnig es ist" um jeden Preis 
aufrecht erhält, das verstehe ich nicht.
Und bei C++ ist es auch nicht anders :-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> Und bei C++ ist es auch nicht anders :-)

Gut, die bisher vorgebrachten Beispiele sind mehr akademischer Natur, 
gebe ich zu.

Daher C++

class ParamaterSet
{
public:

   void Set( const char * name, int value );
   void Set( const char * name, double value );
   void Set( const char * name, const char * value );
};

int main()
{
  ParameterSet params;
  ...

  params.Set( "Anzahl", 5 );
  params.Set( "Name", "Hugo" );
  params.Set( "Name", NULL );
}

schnell, ohne lang zu analysieren, beantworte man die Frage: welche 
Funktion wird beim letzten Set Aufruf aufgerufen.
Wer
   void ParamaterSet::Set( const char * name, const char * value );
sagt, liegt leider falsch.
NULL hat in C++, obwohl explizit für Pointerverwendung vorgesehen, den 
Datentyp int. Das man nicht straffrei einen void* an jeden anderen 
beliebigen Datenpointer zuweisen darf, ist IMHO ein Fortschritt, 
trotzdem hätte man für NULL (der explizit als void* hätte definiert 
werden können) die Erlaubnis geben können. Es wäre zwar eine 
Ausnahmeregelung gewesen, aber eine IMHO sinnvolle.

König Lookup muss man kennen
class A
{
public:
  void foo( int value );
};

class B : public A
{
public:
  void foo( double value );
};

int main()
{
  B obj;

  obj.foo( 5 );
}

welches foo wird benutzt?
Es ist B::foo( double )

Überraschend? Für Neulinge, die sich nie damit beschäftigt haben schon, 
ist doch offenbar A::foo( int ) ein viel besserer Match für eine beim 
Aufruf angegebene 5

"Wenn etwas eine Deklaration sein kann, dann ist sie das auch"

Von der eigenartigen Ausnahme, dass main(), obwohl der Returntyp int 
sein muss, kein explizites return braucht, red ich schon gar nicht mehr.

Und so gibt es noch viele andere Dinge.


Wie weiter oben schon vorgebracht wurde: Bei N.Wirth und seinen Sprachen 
gibt es solche auf den ersten Blick seltsamen Sachen nicht.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:

> werden können) die Erlaubnis geben können. Es wäre zwar eine
> Ausnahmeregelung gewesen, aber eine IMHO sinnvolle.

Wäre auch ohne Ausnahmeregelung gegangen. "null" (oder "nil") als 
Keyword, mit implizitem eigenem zu allen Pointern zuweisungskompatiblem 
Datentyp. Und schon hätte Stroustrup ein verhasstes #define weniger 
gehabt.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> Wäre auch ohne Ausnahmeregelung gegangen. "null" (oder "nil") als
> Keyword, mit implizitem eigenem zu allen Pointern zuweisungskompatiblem
> Datentyp.

Und das würdest du nicht als "Ausnahmeregelung" bezeichnen?

> Und schon hätte Stroustrup ein verhasstes #define weniger gehabt.

Statt "hätte gehabt" muß es "wird haben" heißen. In C++0x wird es das 
nämlich geben.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:

> Und das würdest du nicht als "Ausnahmeregelung" bezeichnen?

Nein, das würde ich tatsächlich nicht.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann haben wir wohl recht unterschiedliche Meinungen darüber, was eine 
Ausnahme ist. Für mich ist jedenfalls ein spezielles Symbol, das als 
einziges in der gesamten Sprache zu allen Zeigertypen 
zuweisungskompatibel ist, ganz offensichtlich eine Ausnahme.

Autor: Andreas Ferber (aferber)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus schrieb:
> Dann haben wir wohl recht unterschiedliche Meinungen darüber, was eine
> Ausnahme ist. Für mich ist jedenfalls ein spezielles Symbol, das als
> einziges in der gesamten Sprache zu allen Zeigertypen
> zuweisungskompatibel ist, ganz offensichtlich eine Ausnahme.

Nur ist das dann schon immer eine Ausnahme gewesen. Nur ein Integer mit 
dem Wert 0 darf in einen Pointer umgewandelt werden, Integer mit anderen 
Werten nicht. Nichtmal die in C noch erlaubte Umwandlung Pointer -> 
Integer -> Pointer ist in C++ erlaubt, ausser es handelt sich eben um 
Nullpointer.

Das neue Keyword ist also nicht mehr Ausnahme als der bisherige Stand 
auch, und bietet den Vorteil, dass es nicht mehr zu solchen 
Überraschungen wie oben führt, wenn Überladung von Funktionen ins Spiel 
kommt.

Andreas

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Andreas Ferber schrieb:
> Das neue Keyword ist also nicht mehr Ausnahme als der bisherige Stand
> auch, und bietet den Vorteil, dass es nicht mehr zu solchen
> Überraschungen wie oben führt, wenn Überladung von Funktionen ins Spiel
> kommt.

Richtig, aber ich habe auch nur der Behauptung widersprochen, daß dies 
ohne Ausnahmeregelung auskäme und nicht geschrieben, daß es vorher keine 
gegeben hätte.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.