2017-10-12 4 views
0

Ich habe versucht, ein wenig mit Zeiger für einen bestimmten Wert von 'i' zu spielen und was ich herausgefunden habe, dass zwei verschiedene Adressen für die Deklaration% u und% lu,% llu zugewiesen sind. Wie ist möglich, dass eine Variable zwei verschiedene Adressen auf der gleichen Instanz der Ausführung haben kann -Wie kann eine Variable zwei verschiedene Adressen zum selben Zeitpunkt haben?

#include <stdio.h> 
int main(void) 
{ 
    int i; 
    float f; 
printf("\nEnter an integer:\t"); 
scanf("%d",&i); 

    printf("\nValue of address of i=%u",&i); 
    printf("\nvalue of address of i=%d",&i); 
    printf("\nValue of address of i=%lu",&i); 
    printf("\nValue of address of i=%llu",&i); 

    printf("\nvalue of i=%d",i); 
    printf("\nvalue of i=%u",i); 
    printf("\nvalue of i=%lu",i); 
    printf("\nvalue of i=%llu\n",i); 

} 

Dies ist die Ausgabe -

[email protected]:~/Desktop/Daily programs/pointers$ ./pointer001 

    Enter an integer: 12 

    Value of address of i=1193639268 
    value of address of i=1193639268 
    Value of address of i=140725797092708 
    Value of address of i=140725797092708 
    value of i=12 
    value of i=12 
    value of i=12 
    value of i=12 

Hier können wir deutlich sehen, dass für% u und% d die Adresse ist 1193639268 (obwohl die Ausgabe von% d und% u möglicherweise nicht in allen Fällen gleich ist) und die Ausgabe von% lu und% llu ist 140725797092708 und was ist ihre physische Bedeutung.

Antwort

6

Der richtige Formatspezifizierer zum Drucken eines Zeigers ist %p.

die falschen Formatbezeichner verwenden, wie %d, %u, %lu oder %llu ruft undefined behavior.

Als das spezifische Verhalten Sie sehen, einen Zeiger auf Ihre speziellen Implementierung ist wahrscheinlich ein 8-Byte-Wert, während ein int oder unsigned int wahrscheinlich ein 4-Byte-Wert ist. Wenn Sie %d oder %u verwenden, werden nur die ersten 4 Byte des 8-Byte-Werts gelesen, der an die Funktion übergeben wurde, und dieser Wert wird gedruckt. Wenn Sie dann %lu oder %llu verwenden, werden alle 8 Bytes als solche gelesen und gedruckt.

Da Sie ein undefiniertes Verhalten aufrufen, können Sie sich nicht darauf verlassen, dass diese Ausgabe konsistent ist. Zum Beispiel wird das Kompilieren im 32-Bit-Modus im Vergleich zum 64-Bit-Modus wahrscheinlich zu anderen Ergebnissen führen. Am besten zu verwenden %p, und auch den Zeiger auf void * zu werfen, da das der spezifische Zeigertyp ist, der von %p erwartet wird.

+2

Detail: Der richtige Formatbezeichner zum Drucken eines 'void *' -Zeichens ist '"% p "'. '"% p "' funktioniert möglicherweise nicht für ein 'int *', aber üblich. – chux

+1

@chux Guter Punkt. Ich habe dieses Detail hinzugefügt – dbush

2

Es tut es nicht. Sie verwenden nur falsche Formatbezeichner für Zeigertypen.

Das Verhalten beim Ausführen ist nicht definiert. Die Ausgabe, die Sie beobachten, ist eine Manifestation dieses undefinierten Verhaltens.

Verwenden Sie% p für einen Zeiger, und das Zeigerargument auf einen const void * -Typ (viele Compiler sind locker in diesem letzten Punkt, aber es ist nichtsdestotrotz gute Praxis).

3

Sie verwenden den falschen Formatbezeichner, der undefined behavior ergibt. In diesem speziellen Fall ist das Verhalten, dass 1193639268 (0x47257D64) ist der untere Teil des 140725797092708 (0x7FFD47257D64)

Die richtige Formatangabe für Adressen ist %p

4

Es gibt nur eine Adresse. Sie verwenden Integer-Druckcodes mit unterschiedlichen Breiten, daher sehen Sie manchmal 32 Adressenbits und manchmal 64 Bit Adressen. Wie viel gültig ist, hängt von Ihrem System ab; bei einem 32-Bit-System bedeutet das Drucken von 64 Bits, daß 32 Bits des Wertes Müll sind; Bei einem 64-Bit-System bedeutet das Drucken von 32 Bit, dass Sie die Hälfte des Zeigers weglassen.

Es gibt einen dedizierten Formatcode, %p, der zum Drucken von Zeigern gedacht ist, verwenden Sie das, keine ganzzahligen Druckcodes.

Verwandte Themen