Die Deklaration:
int b[2] = {1, 2};
Erstellt ein Array von zwei int
mit den Werten 1
, 2
.
in einer Systemgröße von int Angenommen 4-Byte, dann wird das Array b[]
im Speicher etwas gespeichert werden soll, wie die folgende:
first ele +----------+
(b + 0) ---►| 1 | 0xbf5c787c <----- &b , (c + 0)
next ele +----------+
(b + 1) ---►| 2 | 0xbf5c7880 <------------- (c + 1)
+----------+
(b + 2) ---►| ? | 0xbf5c7884 <----- (&b + 1) next array
+----------+
---►| ? | 0xbf5c7888
+----------+
---►| ? | 0xbf5c788c <----- (&b + 2) next array
+----------+
---►| ? | 0xbf5c7890
+----------+
? means garbage value
b[] array in memory from 0xbf5c787c to 0xbf5c7880
each cell is four bytes
In obigen Diagramm Speicherzellen mit dem Wert ?
garbage Werte bedeuten und nicht zugewiesen (Speicher von 0xbf5c7884
ist nicht für unser Array reserviert).Die Werte 1
, 2
werden im Speicher unter der Adresse 0xbf5c787c
und 0xbf5c7880
gespeichert, die im Array b[]
zugewiesen sind.
Lassen Sie uns anstelle von Druckwerten, drucken wir Adressen des Speichers, die Sie in Ihrem Code Zugriff mit (c + i)
und (&b + i)
für diese betrachten folgendes Programm:
#include<stdio.h>
int main(){
int b[2] = {1, 2};
int i = 0;
int *c = &b; //Give warning: "assignment from incompatible pointer type"
printf("\n C address: "); // outputs correct values
for (i = 0; i < 2; i++) {
printf("%p ", (void*)(c + i));
}
printf("\n B address: "); // outputs incorrect values/ and behaving differently
for (i = 0; i < 2; i++) {
printf("%p ", (void*)(&b + i)); // Undefined behavior
}
return 1;
}
Ausgänge:
C address: 0xbf5c787c 0xbf5c7880
B address: 0xbf5c787c 0xbf5c7884
prüfen diese Code funktioniert @Codepade
Beachten Sie, (c + i)
druckt korrekte Adresse der Zellen mit Wert 1
,Daher sind die Ausgaben in Ihrem ersten Code korrekt. Während (&b + i)
einen Adresswert ausgibt, der nicht dem Array b[]
zugeordnet ist (also außerhalb des Arrays b[]
) und der Zugriff auf diesen Speicher zur Laufzeit ein nicht definiertes Verhalten (nicht vorhersagbar) ergibt.
Tatsächlich gibt es einen Unterschied zwischen b
und &b
.
b
ist ein Array und seine Art ist int[2]
, b
in int*
als Adresse in den meisten Ausdrücke für erstes Element abklingt (lies: some exceptions where array name not decaying into a pointer to first element?). Und b + 1
zeigt auf nächste int
Elemente in Array (beachten Sie das Diagramm).
&b
ist Adresse kompletten Array und seine Art ist int(*)[2]
, (&b + 1)
Punkte zum nächsten Array vom Typ int[2]
, die nicht in Ihrem Programm (Bekanntmachung im Diagramm, dass in dem (&b + 1)
Punkten) zugeordnet ist.
Um einige andere interessante Unterschiede zwischen b
und &b
wissen lassen: What does sizeof(&array)
return?
Im ersten Code Schnepfe, wenn Sie c = &b
tun, Sie Adresse des Array int*
zuweisen (in unserem Beispiel 0xbf5c787c
). Mit GCC-Compiler wird diese Anweisung warnen: "Zuweisung von inkompatiblen Zeigertyp".
Da c
Zeiger auf int
ist, wird *(c + i)
gedruckt Integer bei Adresse (c + i)
gespeichert. Für i = 1
zeigt der Wert (c + 1)
auf das zweite Element im Array (in unserem Beispiel 0xbf5c7880
) daher *(c + 1)
druckt 2
korrekt.
Bezüglich der Zuweisung int *c = &b;
im ersten Code empfehle ich sehr lesen @ AndreyT answer unten. Die korrekte und einfache Art und Weise Array-Elemente zuzugreifen Zeiger verwenden, wird wie folgt aussehen:
int b[2] = {1, 2};
int *c = b; // removed &, `c` is pointer to int
int i;
for (i = 0; i < 2; i++){
printf("%d ", *(c + i));
// printf("%d ", c[i]); // is also correct statement
}
In Ihrem zweiten Code, das Hinzufügen i
-&b
es Ihnen Speicher *
Dereferenzierungsoperator mit Zugriff außerhalb zugewiesenen Speicher und in printf Anweisung zeigt machen Ursache ungültiger Speicherzugriff und Verhalten dieses Codes zur Laufzeit ist Undefined. Das ist der Grund dafür, dass sich der zweite Code bei unterschiedlicher Ausführung anders verhält.
Ihr Code kompiliert, weil syntaktisch es richtig ist, aber zur Laufzeit kann der Zugriff auf nicht zugeordneten Speicher vom OS-Kernel erkannt werden. Dies kann dazu führen, dass der OS-Kernel einen Signal-Core-Dump an den Prozess sendet, der die Exception verursacht hat (interessant zu beachten: wenn das Betriebssystem einen Speicherrechtsverletzung durch einen Prozess erkennt) - Ein ungültiger Zugriff auf gültigen Speicher ergibt: SIGSEGV und Zugriff auf eine ungültige Adresse : SIGBUS). Im Wertfall kann Ihr Programm ohne Fehler ausgeführt werden und Müll-Ergebnisse erzeugen.
Bezüglich zweiten Code, korrekte Art und Weise Array 'Zeiger auf Array' zu drucken wie weiter unten sein:
#include<stdio.h>
int main(){
int b[2] = {1, 2};
int i;
int (*c)[2] = &b; // `c` is pointer to int array of size 2
for(i = 0; i < 2; i++){
printf(" b[%d] = (*c)[%d] = %d\n", i, i, (*c)[i]); // notice (*c)[i]
}
return 1;
}
Ausgang:
b[0] = (*c)[0] = 1
b[1] = (*c)[1] = 2
prüfen @codepade. Point to be notice Klammern um *c
wird als Priorität von []
Operator ist dann höher als *
Dereferenz Operator (während, wenn Sie Zeiger auf int verwenden Sie keine Klammern wie in oben genannten Code) benötigt.
Wofür wird 'k' verwendet? – 0x499602D2
zweiten Code - [undefined Verhalten] (http://en.wikipedia.org/wiki/Undefined_behavior) so verhält sich anders –
+1 nette Frage, aber leicht beantwortbar, immer noch nützlich :) – 0decimal0