a = & b vs * a = & b - Zeigerzuweisung

7

Ich habe einen Zeiger und eine Variable:

%Vor%

Gibt es einen Unterschied zwischen Zuweisungen

? %Vor%

und

%Vor%

und wie heißen sie (wie Zeigerdeklaration oder etwas)?

    
Sumit Ramteke 02.01.2017, 09:15
quelle

11 Antworten

7

Achten Sie auf Typen links und rechts von = .

&b ist int * , a ist auch int * , aber *a ist int .

Es ist ein wenig verwirrend, dass * unterschiedliche Bedeutungen hat:

int *a; - hier * bedeutet, dass a ein Zeiger ist;

*a = ...; - hier * bedeutet, dass wir nicht die in a gespeicherte Adresse ändern, sondern den Wert, der sich an der Adresse befindet.

So a = &b bedeutet "schreibe die Adresse von b in a ",

aber *a = &b bedeutet "schreibe die Adresse von b in *a , d. h. auf die Adresse, die in a gespeichert ist."

Lassen Sie uns vorschlagen, dass wir diese Situation haben:

%Vor%

Momentan ist a 0x0004 und *a ist 90 .

Wenn Sie a = &b verwenden, wird a 0x0002 und *a wird 70 sein.

Aber wenn Sie *a = &b machen, wird sich a nicht ändern, aber *a , d. h. Wert an der Adresse 0x0004 , ändert sich zu 0x0002 .

    
Pavel 02.01.2017, 09:30
quelle
18

Typen sind wichtig.

  • Im Fall von a=&b ist die Zuweisung gültig. Sie ordnen die Adresse einer Ganzzahl (Typ: int * ) einer anderen Variablen vom Typ int * zu, also ist dies legitim.

  • Im Falle von *a=&b ist dies ein Constraint-Verstoß (für den Zuweisungsoperator, siehe Kapitel §6.5.16.1 / p1, Constraints , für Simple) Zuweisung ) und somit keine gültige C-Syntax, die nicht von einem kompilierenden Compiler kompiliert werden muss. Um eine gültige C-Syntax zu erhalten, müssen wir eine typecast erzwingen, etwa

    %Vor%

    würde es zu einer syntaktisch gültigen C-Anweisung machen, die die erforderliche Einschränkung erfüllt.

    Auch danach ist das Ergebnis eine Implementierung. #note Hier versuchst du im Prinzip, die Adresse einer Ganzzahl (Typ: int * ) einer anderen Variablen vom Typ zuzuordnen int ( *a hat den Typ int ). Die Konvertierung von einem Zeiger in eine Ganzzahl ist ein implementierungsdefiniertes Verhalten.

    Zitat C11 , Kapitel §6.3.2.3, Zeiger

      

    Jeder Zeigertyp kann in einen Integer-Typ konvertiert werden. Außer wie zuvor angegeben, die   Ergebnis ist implementierungsdefiniert. Wenn das Ergebnis nicht im Integer-Typ dargestellt werden kann,   Das Verhalten ist nicht definiert. [....]

  

[....] Und wie heißen sie?

Beide sind Zuweisungsanweisungen.

Hinweis:

Betrachtet a zeigt bereits auf einen gültigen Speicherort. Andernfalls ruft das Deaktivieren eines ungültigen Zeigers undefiniertes Verhalten auf.

    
Sourav Ghosh 02.01.2017 09:16
quelle
3
  

Gibt es einen Unterschied zwischen Zuweisungen

? %Vor%      

und

%Vor%

Ja. Im ersten Fall haben a und &b (Adresse von b ) beide den Typ int * . Sie sind zuweisbar.
Im Falle von *a = &b ist *a vom Typ int , während &b vom Typ int * ist. Bothe-Typen sind inkompatibel und der Typ &b wird nicht explizit in den Typ *a konvertiert. Dies ist eine Einschränkungsverletzung. Das heißt: int -Typen können keine Zeigerobjekte halten. Die einzigen Integer-Typen, die das Zeigerobjekt halten können, sind intptr_t und uintptr_t .

7.20.1.4 Ganzzahlige Typen, die Objektzeiger halten können

  

1 Der folgende Typ bezeichnet einen signierten Integer-Typ mit der Eigenschaft, dass ein beliebiger gültiger Zeiger auf void in diesen Typ konvertiert und dann in den Zeiger auf void zurückkonvertiert werden kann. Das Ergebnis wird mit dem ursprünglichen Zeiger verglichen :

%Vor%      

Der folgende Typ bezeichnet einen Ganzzahl-Datentyp ohne Vorzeichen mit der Eigenschaft, dass jeder gültige Zeiger auf void in diesen Typ konvertiert und dann wieder in den Zeiger auf void konvertiert werden kann. Das Ergebnis wird mit dem ursprünglichen Zeiger verglichen:

%Vor%      

Diese Typen sind optional.

  

und wie heißen sie (wie Zeigerdeklaration oder etwas)?

Sie sind Zuweisungsanweisungen.

    
haccks 02.01.2017 11:29
quelle
3

Ein bemerkenswerter Unterschied ist, dass die zweite Zuweisung schlecht ausgebildet ist C (wegen Einschränkung Verletzung ):

%Vor%
  

Fehler: Zuweisung macht Integer aus Zeiger ohne eine Besetzung   [-Wint-Konvertierung]

C11 §6.5.4 / 3, Darsteller:

  

Conversions, die Zeiger enthalten, außer wenn dies von der   Einschränkungen von 6.5.16.1, soll explizit angegeben werden   Cast .

Die Anforderung der expliziten Umwandlung wurde in C89 eingeführt, um eine schlechte Praxis der impliziten Konvertierung zwischen Ganzzahl- und Zeigertypen zu verbieten.

Die einzige Ausnahme von dieser Regel besteht darin, dass Sie den Zeigerwert mit 0 integer constant zuweisen können, was die Nullzeigerkonstante darstellt:

%Vor%     
Grzegorz Szpetkowski 02.01.2017 09:31
quelle
3

Wie alle anderen Antworten haben wir bereits auf die Variablen int *a und int b hingewiesen:

  • die Zuweisung a = &b ist gültig (und weist dem Zeiger b die Adresse von a zu, sodass *a für den Zugriff auf b verwendet werden kann), während
  • Die Zuweisung *a = &b ist eine Constraint-Verletzung, da sie versucht, die Adresse von b der Ganzzahl zuzuordnen, auf die a zeigt, was ohne eine explizite Umwandlung nicht erlaubt ist.

Was? könnte dich verwirren, ist jedoch, dass die Variablendeklaration:

%Vor%

ist gültig und macht genau dasselbe wie:

%Vor%

Das ist eine sehr bequeme Abkürzung, da Sie fast immer eine Variable initialisieren möchten, sobald Sie sie deklarieren (um nur sicherzustellen, dass Sie sie nicht versehentlich versuchen, bevor sie initialisiert wird). Aber es kann verwirrend sein, wenn Sie diese Syntax zum ersten Mal sehen, da aussieht , als ob Sie &b auf *a zuweisen, wenn es tatsächlich a selbst ist, das mit dem Wert initialisiert wird %Code%. Dies ist nur etwas, das Sie lernen müssen: Variableninitialisierung ist nicht das Gleiche wie normale Zuweisung, obwohl sie zum Verwechseln ähnlich aussieht.

    
Ilmari Karonen 02.01.2017 16:41
quelle
2

Bei den Typen wären die folgenden Zuweisungen gültig:

%Vor%

Im zweiten Fall muss a auf einen gültigen Speicherort zeigen oder das Verhalten ist nicht definiert.

%Vor%

ist eine Constraint-Verletzung und der Compiler wird Sie anschreien.

    
John Bode 02.01.2017 11:21
quelle
2
  

Der erste, int a = & amp; b; kopiert die Adresse der Variablen "b" in die    "a".

     

Die zweite, int * a = & amp; b; kopiert die Adresse der Variablen "b" in die   Standort "a" zeigt auf.

    
user7348672 02.01.2017 12:15
quelle
1

Der erste ist ok, aber der zweite ruft UB auf. (Es sei denn, a zeigt auf einen gültigen Speicher)

    
coderredoc 02.01.2017 09:18
quelle
1

Sicher gibt es differents zwischen ihnen
& stellen Zeiger dar (vom Zeiger können Sie Wert erhalten)
* stellen Wert dar
a=&b (stellen Sie einen gleichen Punkt von b dar)
*a=&b (repräsentiert den Wert einen gleichen Punkt von b)

Helped Tutorial

    
Aya Aboud 02.01.2017 09:25
quelle
1

Lassen Sie mich zuerst den Unterschied zwischen Integer-Variablen und Zeigervariablen klären:

(1) Integer-Variable (z. B .: int b , in diesem Fall) wird zum Speichern des Werts einer Ganzzahl (der Länge 4 Byte) verwendet. Der Wert von 'b' wird an einem Speicherort gespeichert (zB 0x00000001).

(2) Eine Zeigervariable (z. B. int * a ) wird verwendet, um den Speicherplatz einer ganzzahligen Variablen zu speichern. Das heißt, in 'a' können wir die Adresse einer Integer-Variablen speichern. Der Wert, auf den eine Zeigervariable zeigt, kann durch den Operator '*' dereferenziert werden. Also hat 'a' die Adresse und '* a' den Wert, auf den der in a enthaltene Wert (Adresse) zeigt.

Beantworten Sie jetzt Ihre Frage:

Nehmen wir an, dass b = 4 und die Adresse von b (& amp; b) 0x00000001 (Hexadezimalnotation) ist.

In der ersten Typzuweisung a = & amp; b wird die Adresse der Variablen Ganzzahl b in a gespeichert (da a eine Zeigervariable ist). Jetzt hat 'a' den Wert 0x00000001 und '* a' hat 4.

In der zweiten Typzuweisung * a = & amp; b wird die Adresse der Variablen b an dem Speicherplatz gespeichert, auf den a zeigt, d. h. in der 0x00000001-Speicherstelle wird der Wert 0x00000001 selbst sein. Jetzt hat 'a' den Wert 0x00000001 und '* a' hat auch den gleichen Wert 0x00000001.

    
LearningC 02.01.2017 11:54
quelle
1
%Vor%

Jede Variable var vom Typ T hat einen Speicherort im Speicher, dessen Adresse entweder vom Compiler oder von den statischen oder dynamischen Linkern zugewiesen wird. Die Adresse einiger Variablen kann mit & amp; var erhalten werden und hat den Typ pointer to T . Wenn Sie also den Operator & anwenden, verschachteln Sie den Typ innerhalb eines anderen Zeigers. a = & amp; b ist richtig.

Auf der anderen Seite ist *a=&b nicht korrekt. Sie versuchen, in der Variablen * a (mit dem Typ int ) einen Zeiger auf die Basisadresse der Variablen b (vom Typ pointer to int ) zu speichern. In den Architekturen, in denen der Zeiger 64 Bits hat und int 32 Bits hat, führt dies zu einem Fehler. Auf den Architekturen hingegen, auf denen Zeiger und Int die gleiche Länge haben, ist dies möglich, wenn Sie einen Cast einfügen. Der Compiler fügt nicht automatisch eine Nötigung von int* nach int ein.

    
alinsoar 02.01.2017 12:03
quelle

Tags und Links