Definition 'Dereferenzierung'



  • Rotondo schrieb:

    int a;
    int* ptr; // keine Dereferenzierung , sondern Deklaration eines Zeigers
    aber wie nennt man hier den * Operator ?

    Richtig, das ist eine Deklaration, aber es gibt hier keinen *-Operator. Das *-Token ist hier Teil der Typbezeichnung, kein Operator.

    Handelt es sich im folgenden Beispiel von einem Dereferenzierungsoperator und einer Dereferenzierung sprechen ?

    *ptr = &a; //FEHLER! &a ist ein Pointer auf int, *ptr ist der dereferenzierte Pointer und daher ein int.
    *ptr = 17; //hier wird der Pointer dereferenziert

    Eine Dereferenzierug ist nicht viel mehr als "dem Zeiger nachgehen und das dahinterliegende Objekt erhalten".



  • Also ist hier der *-Operator ein 'Typenbezeichner' ?

    int* ptr;
    *ptr = &a

    und hier ein Dereferenzierungsoperator:

    *ptr = 17;

    ??



  • ... oder gibt es demnach den Begriff:
    'Dereferenzierungsoperator'
    nicht.

    Und das * gehört nur zum Typ. Und Dereferenzierung ist nur der Zugriff auf ein Objekt über einen Zeiger ?


  • Mod

    Rotondo schrieb:

    Also ist hier der *-Operator ein 'Typenbezeichner' ?

    int* ptr;
    *ptr = &a

    und hier ein Dereferenzierungsoperator:

    *ptr = 17;

    ??

    Auch *ptr = &a ist eine Dereferenzierung, auch wenn hier ganz etwas anderes passiert als du wahrscheinlich meinst. Hier wird nämlich dem Objekt auf das ptr zeigt der Wert &a zugewiesen. Dazu muss dem Pointer auch gefolgt werden.

    Dies ist jedoch ganz etwas anderes als den Pointer ptr auf das Objekt a Zeigen zu lassen, dies geht so: ptr=&a



  • Sorry Sepp, natürlich sollte es so lauten:

    int *ptr;
    ptr = &a;

    nur suche ich nach der Begriffdefinition:

    *ptr = 17; // Ist das *-hier ein Dereferenzierungsoperator oder ein Typenbezeichner ?



  • Deklaration und Adresszuweisung aber keine Dereferenzierung ?
    * ist hier ein Typenbezeichner:

    int* ptr = &a

    Dereferenzierung mit einem Dereferenzierungsoperator ?

    *prt = 17;

    richtig ???



  • Rotondo schrieb:

    *ptr = 17; // Ist das *-hier ein Dereferenzierungsoperator oder ein Typenbezeichner ?

    Es ist ein Dereferenzierungsoperator. Du siehst hier ja auch nirgends einen Typen oder?
    * alleine ist nie ein Typbezeichner, sondern nur in Zusammenhang mit einem Typnamen. In int* ptr ist also int* der Typbezeichner, ptr der Variablenname.



  • Das wichtigste wurde gesagt. Vielleicht noch ein paar Worte zu Deklarationen:

    int * ptr;
    ^^^ ^^^^^
    (1)  (2)
    

    1: Typ-Spezifizierer
    2: Deklarator

    Im Prinzip sagt eine solche Deklaration, dass der zweite Teil ( *ptr ), falls er als Ausdruck im Programm später verwendet wird, vom Typ int ist. Daraus folgt, dass ptr ein Zeiger ist. Das trifft auf so ziemlich alles andere auch zu (Funktionen, Arrays, ...) -- mit Ausnahme von Referenzen. Referenzen werden mit & als "Präfixoperator" deklariert, ohne dass explizit eine Dereferenzierung bei der weiteren Nutzung der Referenz durchgeführt werden muss.

    *ptr = &a;
    *ptr = 17;

    Das erste lässt sich nicht kompilieren. *ptr ist ein Lvalue-Ausdruck vom Typ int. &a ist ein Ausdruck, der die Adresse eines int-Objekts liefert. Du kannst keinem int-Objekt die Adresse eines anderen int-Objekts zuweisen. int s speichern Ganzzahlen aber keine Adressen. Das, was Du wahrscheinlich machen wolltest, war das hier: ptr = &a;

    In der zweiten Zeile kann man von einer Dereferenzierung sprechen. Der Wert 17 wird in dem int-Objekt gespeichert, auf das der Zeiger ptr zeigt.



  • krümelkacker schrieb:

    Du kannst keinem int-Objekt die Adresse eines anderen int-Objekts zuweisen.

    Prinzipiell geht das schon. Gerade der Typ int ist für die Speicherung einer Adresse geeignet, da er genau so Groß wie die Wortbreite des Prozessors (OS außen vor) ist.
    Und in C lässt sich das auch - mit Warnung - kompilieren. In C++ geht's mit einem cast.
    Welchen Sinn das macht sei mal dahingestellt, aber gehen tut's schon und ist auch nicht zu böse.

    int main()
    {
    	int  a;
    	int* ptr = new int;
    
    	*ptr = reinterpret_cast<int>(&a);
    
    	return 0;
    }
    


  • FrEEzE2046 schrieb:

    krümelkacker schrieb:

    Du kannst keinem int-Objekt die Adresse eines anderen int-Objekts zuweisen.

    Prinzipiell geht das schon. Gerade der Typ int ist für die Speicherung einer Adresse geeignet, da er genau so Groß wie die Wortbreite des Prozessors (OS außen vor) ist.

    Nein, das ist nirgends festgelegt und definiert. Es bietet sich aus Effizienzgründen an, das so zu machen, und auf vielen heutigen Standard-Systemen werden die Compiler auch entsprechend implementiert, aber das heißt nicht dass es immer und überall so sein muss.



  • pumuckl schrieb:

    Nein, das ist nirgends festgelegt und definiert. Es bietet sich aus Effizienzgründen an, das so zu machen, und auf vielen heutigen Standard-Systemen werden die Compiler auch entsprechend implementiert, aber das heißt nicht dass es immer und überall so sein muss.

    Okay, richtig. Da C in erster Linie Portabilität betrachtet spielt die Bitbreite eines Typs nur eine untergeordnete Rolle und ist zum Teil Compiler abhängig.

    Aber, rein theoretisch kann ein Integer dann auch 8 Bit breit sein. 100% Portabilität erreicht man dann auch nur durch selbstdefinierte Typen je nach Zielsystem. Aber ich denke doch mal, dass wir schon bei der Verwendung eines Datentyps davon ausgehen können müssen, wie groß ein Typ ist. Viele Programmmodule würden sonst überhaupt nicht laufen.

    Beim AVR-GCC ist int auch 16 Bit breit. Wer hardwarenah programmiert sollte auch wissen wie groß die Typen sind. Macht man das alles voll abstrakt kann einem das wohl fast egal sein.


  • Mod

    Also bei meinem System ist sizeof(int)==4 und sizof(int*)==8 und meine Konfiguration ist nun wirklich nicht exotisch (GCC unter 64-Bit Linux).

    P.S.: int ist übrigens laut Standard mindestens 16 Bit groß.



  • FrEEzE2046 schrieb:

    Aber, rein theoretisch kann ein Integer dann auch 8 Bit breit sein.

    Richtig.

    100% Portabilität erreicht man dann auch nur durch selbstdefinierte Typen je nach Zielsystem.

    Oder indem man sich nicht von Dingen abhängig macht, die im Standard nicht genauer spezifiziert sind.

    Aber ich denke doch mal, dass wir schon bei der Verwendung eines Datentyps davon ausgehen können müssen, wie groß ein Typ ist.

    Nein, wieso? Und für den Fall wo wir es brauchen gibts sizeof()

    Viele Programmmodule würden sonst überhaupt nicht laufen.

    Das mag für einiges gelten, was in C geschrieben wurde und vermutlich auch einiges, was in oldscool/C-Style C++ geschrieben wurde. Bei sauberem, aktuellem, portablem C++ sollte man sich nach Möglichkeit nur auf das stützen, was der Standard garantiert, dann liegts nämlich am System wenn mangels Standardkonfomrität etwas nicht funktioniert und nicht am Code.

    Ich würde krümelkackers Aussage und vor allem deine Erwiderung also etwas umformulieren:

    "Du kannst einem int-Objekt prinzipiell keine Adresse eines anderen in-Objektes zuweisen." - "In ganz bestimmten, nicht portablen und vom Standard nicht garantierten Fällen kann man da per reinterpret_cast was dran drehen."



  • Wenn man unbedingt einen Zeiger in einen Ganzzahltyp casten muss, dann bitte in size_t. Dieser Typ ist garantiert so groß wie ein Zeiger.



  • pumuckl schrieb:

    "Du kannst einem int-Objekt prinzipiell keine Adresse eines anderen in-Objektes zuweisen." - "In ganz bestimmten, nicht portablen und vom Standard nicht garantierten Fällen kann man da per reinterpret_cast was dran drehen."

    Herrlich 😃 .
    Aber du hast natürlich recht. Man soll ja Wissen nach dem Standard vermitteln und nicht nur "meist funktionierende" Ausnahmen lehren.

    Janjan schrieb:

    Wenn man unbedingt einen Zeiger in einen Ganzzahltyp casten muss, dann bitte in size_t. Dieser Typ ist garantiert so groß wie ein Zeiger.

    size_t ist ein typedef auf unsigned int. Mehr nicht.



  • Janjan schrieb:

    Wenn man unbedingt einen Zeiger in einen Ganzzahltyp casten muss, dann bitte in size_t. Dieser Typ ist garantiert so groß wie ein Zeiger.

    Wo steht das?

    FrEEzE2046 schrieb:

    size_t ist ein typedef auf unsigned int. Mehr nicht.

    Wirklich immer?


  • Mod

    pumuckl schrieb:

    FrEEzE2046 schrieb:

    Aber, rein theoretisch kann ein Integer dann auch 8 Bit breit sein.

    Richtig.

    Falsch. Laut C++ Standard müssen die gleichen Limits wie in C89 erfüllt sein und im ANSI C89 Standard, Anhang 4, steht dies:

    ANSI C89 schrieb:

    A.4 IMPLEMENTATION LIMITS

    The contents of a header <limits.h> are given below, in alphabetic
    order. The minimum magnitudes shown shall be replaced by
    implementation-defined magnitudes with the same sign. The values
    shall all be constant expressions suitable for use in #if
    preprocessing directives. The components are described further in
    $2.2.4.2.

    #define CHAR_BIT                         8
             #define CHAR_MAX    UCHAR_MAX  or SCHAR_MAX
             #define CHAR_MIN            0  or SCHAR_MIN
             #define MB_LEN_MAX                       1
             #define INT_MAX                     +32767
             #define INT_MIN                     -32767
             #define LONG_MAX               +2147483647
             #define LONG_MIN               -2147483647
             #define SCHAR_MAX                     +127
             #define SCHAR_MIN                     -127
             #define SHRT_MAX                    +32767
             #define SHRT_MIN                    -32767
             #define UCHAR_MAX                      255
             #define UINT_MAX                     65535
             #define ULONG_MAX               4294967295
             #define USHRT_MAX                    65535
    

    Interessant ist auch, dass CHAR_BIT mindestens 8 ist, bisher hatte ich immer angenommen, dass das Minimum 7 wäre.



  • SeppJ schrieb:

    Falsch. Laut C++ Standard müssen die gleichen Limits wie in C89 erfüllt sein und im ANSI C89 Standard, Anhang 4, steht dies:

    Dir ist schon klar, dass laut diesen Zeilen ein int 16 Bit breit wäre. Muss ich mehr sagen?


  • Mod

    FrEEzE2046 schrieb:

    SeppJ schrieb:

    Falsch. Laut C++ Standard müssen die gleichen Limits wie in C89 erfüllt sein und im ANSI C89 Standard, Anhang 4, steht dies:

    Dir ist schon klar, dass laut diesen Zeilen ein int 16 Bit breit wäre. Muss ich mehr sagen?

    Genau das wollte ich sagen. Aber ja: Du musst mehr sagen, denn ich weiß nicht worauf du hinaus willst 😕 .

    edit: Ahh, ich glaube ich weiß worauf du hinaus willst. Lies nochmal genau:

    ANSI C89 schrieb:

    A.4 IMPLEMENTATION LIMITS

    The contents of a header <limits.h> are given below, in alphabetic
    order. The minimum magnitudes shown shall be replaced by
    implementation-defined magnitudes with the same sign. The values
    shall all be constant expressions suitable for use in #if
    preprocessing directives. The components are described further in
    $2.2.4.2.



  • pumuckl schrieb:

    Wirklich immer?

    size_t ist immer der Rückgabetyp des sizeof() Operators. Laut Standard ist lediglich festgelegt, dass es ein vorzeichenloser integraler Typ ist.

    SeppJ schrieb:

    Genau das wollte ich sagen. Aber ja: Du musst mehr sagen, denn ich weiß nicht worauf du hinaus willst 😕 .

    Ich will dir damit sagen, dass eine Implementierung von int als 32 Bit breiter Typ dann abseits des Standards liegen würde.


Anmelden zum Antworten