Was ist der Unterschied zwischen float-Zeiger und int-Zeiger-Adresse?
Habe ich versucht, diesen code auszuführen,
int *p;
float q;
q = 6.6;
p = &q;
Obwohl es eine Warnung sein, aber ich denke &q
und p
sind von der gleichen Größe, so p
können eine Adresse q
. Aber wenn ich drucken &q
und p
ich bin immer anders ausgegeben.
Das ist meine Ausgabe
*p = 6.600000
q = 0.000000, p = 0x40d33333, &q = 0x7fffe2fa3c8c
Was ist, dass ich bin fehlt?
Und p
und &q
ist die gleiche, wenn beide Zeiger und Variablen-Typ ist der gleiche.
Meine komplette code ist
#include<stdio.h>
void main()
{
int *p;
float q;
q = 6.6;
p = &q;
printf("*p = %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
}
- Zeig bitte den code, die Sie verwenden, um das zu bekommen Ausgabe.
- Wenn ich Sie Recht haben, möchten Sie möglicherweise verwenden Sie eine union...
- Es ist
int main(void)
, nichtvoid main()
.void main()
ist meist nützlich für die Erkennung von Büchern von Autoren, die nicht wissen, C sehr gut. - Sie sind runing auf x86_64? Was dann geschieht wahrscheinlich in
printf("*p = %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
ist, dass der vermeintlicheint
*p
übergeben wird, in einem general purpose register, diedouble
(der beworbene Wert vonq
) übergeben wird, eine floating-point-register, die zwei Zeiger wieder in Allzweck-Registern. - Dann
printf
liest die ersten floating-point-register für die ersten%f
Umwandlung, die zweite floating-point-register für die zweite%f
[zufällig enthält 0], das erste, general purpose - register enthält die bits derfloat
6.6 - druckenp
, und der zweite general purpose register (mit dem Wert vonp
) zu drucken&q
. Das register enthält die Adresse desq
bleibt ungelesen. - Ich weiß int main(void) sollte verwendet werden, immer. Aber in diesem Programm ist es eigentlich egal. Meine wichtigste Frage ist Zeiger beliebigen Typs sein können, aber es wird halten Sie die-Adresse. Dann vergessen Sie die Größe der Datentyp, warum ist die Adresse anders? Und ich weiß auch ich versuche, int* mit Schwimmer, aber ich bin einfach zu Experimentieren mit Zeigern.
- ja, du hast Recht. Ich teilte die
printf
im ersten Teile eine fürvalues
und das zweite füraddresses
. Und das problem war mit%f
, was ich dachte, war, wennp
enthält Adresse vonfloat
es wird immer noch funktionieren wenn ich%f
imprintf
- Anweisung. Aber es lädt die Daten in das Mehrzweckregister dieses problem passiert ist. Nachdem ich split, bekam ich richtigen Adressen, aber die Werte sind doch anders. Danke für die Antwort. 🙂 - Wenn Sie wissen
int main(void)
sollte immer verwendet werden, dann schlage ich vor, Sie immer zu benutzen; zumindest wird es vermeiden, die Beschwerden von Menschen wie mir. Wie, warumint*
undfloat*
gibt verschiedene Formen, ich habe soeben ein paar Absätzen auf meine Antwort.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brauchen Sie, um compiler-Warnungen mehr ernst.
C nicht erforderlich-Compiler ablehnen ungültige Programme, ist es nur eine "Diagnose" für Regelverstöße. Eine Diagnose kann entweder eine Fehler Meldung oder eine Warnung.
Leider, ist es üblich, für den Compilern zu Warnungen für Aufgaben der inkompatible Zeiger-Typen.
Dies ist falsch; es sollte
int main(void)
. Dein compiler kann lassen, Sie mit ihm Weg erhalten, und es kann nicht dazu führen, keine sichtbaren Probleme, aber es gibt keinen Punkt in nicht zu schreiben es richtig. (Es ist nicht ganz so einfach, aber das ist nah genug.)Ist das ok.
p
ist der Typint*
;&q
ist der Typfloat*
. Zuweisen von einen auf den anderen (ohne cast) ist ein constraint-Verletzung. Der einfachste Weg, es zu betrachten ist, dass es einfach illegal.Wenn Sie wirklich wollen, dies zu tun-Belegung verwenden, können Sie einen cast:
aber es gibt selten einen guten Grund, dies zu tun.
p
ist ein Zeiger aufint
; es sollte auf eineint
Objekt, es sei denn, Sie haben eine sehr guten Grund, um es auf etwas anderes zeigen. In einigen Fällen, die Umwandlung selbst kann zu undefiniertem Verhalten.Den
%f
format erfordertdouble
argument (einfloat
argument wird gefördertdouble
in diesem Zusammenhang sofloat
wäre ok). Aber*p
ist der Typint
. Aufrufprintf
mit einem argument vom falschen Typ bewirkt, dass sich Ihr Programm Verhalten undefiniert.%p
erfordert ein argument des Typsvoid*
, nicht nur von jedem Zeiger-Typ. Wenn Sie möchten, drucken Sie einen Zeiger-Wert, Sie sollte es Stimmen zuvoid*
:Ist es wahrscheinlich zu arbeiten, ohne Besetzung, aber wieder, ist das Verhalten undefiniert.
Wenn Sie keine Warnungen beim kompilieren ein Programm, nicht einmal die Mühe, es läuft. Beheben Sie die Warnungen, erste.
Als für die Frage, in Ihrem Titel, Zeiger vom Typ
int*
undfloat*
sind von verschiedenen Arten. Einint*
zeigen sollte, zu einerint
Objekt; einefloat*
zeigen sollte, zu einerfloat
Objekt. Mit dem compiler können Sie mischen, aber das Ergebnis ist entweder von der Implementierung definiert oder undefiniert. Die Sprache C, und besonders viele C-Compiler, mit dem man sofort mit eine Menge Dinge, die nicht viel Sinn.Dem Grund, dass Sie sind verschiedene Arten zu (versuchen zu) verhindern oder zumindest erkennen, Fehler in der Nutzung. Wenn Sie deklarieren ein Objekt vom Typ
int*
Sie sagen, dass Sie beabsichtigen, es auf eineint
Objekt (wenn es nicht ein null-Zeiger). Speichern Sie die Adresse vonfloat
Objekt in Ihremint*
Objekt ist fast sicher ein Fehler. Die Durchsetzung geben Sicherheit können solche Fehler erkannt werden, so früh wie möglich (wenn Ihr compiler gibt eine Warnung statt, wenn das Programm abstürzt, während einer demo für einen wichtigen Kunden).Ist es wahrscheinlich (aber nicht garantiert), dass
int*
undfloat*
sind die gleiche Größe und die gleiche interne Darstellung. Aber die Bedeutung einerint*
Objekt ist nicht "eine Sammlung von 32 (oder 64) bit enthält eine virtuelle Adresse", sondern "etwas, das verweist auf eineint
Objekt".*p
verletzt strict-aliasing, so dass es die UB in sich selbst, unabhängig von dem, was Sie tun, mit Wert.p = (int *) & q;
ist nicht immer legal. C 2011 (n1570) 6.3.2.3 7 sagt, das Verhalten ist undefiniert, wenn das Ergebnis nicht richtig ausgerichtet ist. Es wird auf typische aktuelle Plattformen, so diese in Ordnung ist, wenn Sie planen, Ihrer Zielgruppe entsprechend, aber nicht, wenn Sie planen, für standard-C oder verstehen wollen, die Semantik der C-Spezifikation.int*
undfloat*
unterscheiden können? Ich dachte, Adresse wird immer fester Größe, unabhängig vom Datentyp. Oder gibt es irgendeinen Fall, in demint
gespeichert ist, in verschiedenen Gedächtnis-undfloat
gespeichert ist, in verschiedenen Speicher.?int*
undfloat*
die gleiche Größe haben-aber der C-standard nicht erforderlich ist es. Anderes Beispiel: es gibt Systeme, die sind Wort-adressiert, also eine Maschine, die Adresse verweist auf ein Wort (sagen wir, 4 oder 8 bytes) - aber einechar*
besteht aus einem Rechner-Adresse plus offset innerhalb des Wortes. Bist du wahrscheinlich nicht in einem solchen system ist-aber du bist auch wahrscheinlich nicht brauchen, um zu Pflege über die relativen Größen derint*
undfloat*
. Wenn Sie die Größe einesint*
schreiben Sie einfachsizeof (int*)
(oder wahrscheinlich ehersizeof some_pointer_object
).void main()
. Es ist nur "falsch" in dem Sinne, dass einige andere compiler kann nicht akzeptieren , das dies eine andere Art von falsch zu einer constraint-Verletzung muss diagnostiziert werden, die von allen CompilernDu bist immer Undefiniertes Verhalten, weil Sie vorbei sind die falschen Typen zu
printf
. Wenn Sie sagen, es zu erwarten, dass ein Schwimmer es eigentlich erwartetdouble
- aber Sie passieren eineint
.Als Ergebnis druckt es die falsche information, weil
printf
verlässt sich ganz auf die format-string für den Zugriff auf die Argumente, die Sie übergeben.Zusätzlich zu dem, was ist, sagte teppic,
Betrachten,
In diesem Fall geben wir dem compiler, dass
p
wird auf eine ganze Zahl. So ist es bekannt, dass, wenn wir etwas tun, wie*p
zur Laufzeit, die keine. von bytes, die gleich der Größe einesint
würde gelesen werden.Wenn Sie die assign-Adresse ein Datentyp besetzen
x
Anzahl der bytes an, die ein pointer ist deklariert, halten Sie sich die Adresse von Datentypen, die von weniger bytes alsx
Sie Lesen die falsche Anzahl von bytes bei der Verwendung der dereferenzierungsoperator.float
größer ist alsint
? Es ist erlaubt zu werden, aber wahrscheinlich nicht.void
Zeiger, bevor Sie mit Umweg über es]sizeof (int) == sizeof (double)
; das Verhalten ist ebenso undefiniert auf ein solches system. Riskieren Sie den Eindruck, dass das mischen Zeiger-Typen wie dieses in Ordnung ist, wenn die Größen, die zufällig übereinstimmen. Undp
speziell muss auf eineint
, nicht nur eine ganze Zahl.