2017-07-18 8 views
-1
#include<stdio.h> 
void main() 
{ 
    int n = 2; 
    printf("%c",&n); 
} 

Ausgabe zu verstehen printf Versuch: Leinen Zeiger mit einem char-Bezeichner (% c)

Auf %d es natürlich unter Verwendung gibt die Adresse der Variablen n aber, warum es auf der Verwendung %c L ausgibt?

+5

Da ein Zeiger kein Zeichen ist, ist dieser Code ** undefiniertes Verhalten **. Es könnte auch alles andere machen. Es ist ein zufälliger Effekt auf Ihre spezielle Umgebung, dass der Teil eines Zeigers 'printf()' auswerten wird, wenn Sie versuchen, einen Charakter zu bekommen, übersetzt in H ... –

+2

Ich kann UB riechen. Das einzige, was passiert, ist UB. –

+2

Hehe, so ** jetzt ** ist es plötzlich * "L"? Hast du das Gefühl, dass etwas nicht in Ordnung ist? –

Antwort

-1

Das liegt daran, dass Sie der Funktion printf() gesagt haben, das erste 1 Byte der Adresse von Int n als Zeichen anzuzeigen.

8

Es ist undefined Verhalten, weil Sie falsche Formatspezifizierer verwendet haben.

C11 Standard: 7.21.6.1: Ziffer 9:

Wenn eine Konvertierungsspezifikation ungültig ist, ist das Verhalten undefined. Wenn ein Argument nicht der richtige Typ für die entsprechende Konvertierungsspezifikation ist, lautet das Verhalten undefined.

Es bedeutet, dass alles passieren kann, wenn printf mit einem falschen Formatbezeichner aufgerufen wird.

4

Wie die anderen answer von rsp sagte das Verhalten ist undefiniert und alles kann passieren.

In Ihrem Fall geschieht Folgendes:

Es ein Byte &n liest, weil ein Zeichen von einem Byte Größe ist, die meist 8 Bit lang ist, sehen CHAR_BIT explanation on SO. Dann druckt es es als Zeichen.
Dieses Byte könnte das erste Byte von &n sein, wenn die Typen int* und int an Ihrem Computer identisch sind. Das würde bedeuten, dass Ihre Variable n unter der Adresse 0x48... (big-endian) oder 0x...48 (little-endian) wie 0x48H in der Ascci code liegt. Ich nehme an, dass Ihr Programm Ascii für die Kodierung verwendet, was nicht unbedingt notwendig ist.
(Sie verändert den Charakter H-L aber ich lasse diese Antwort, wie es ist.)
Auch dieses Byte irgendwo in der Mitte des &n liegen, wenn ein int* die Größe eines int an Ihrem System überschreitet.

Sie sollten mit mehr Warnungen kompilieren zum Beispiel aktiviert -Wall in gcc und Sie erhalten:

Warnung: Format '% c' erwartet Argument vom Typ 'int', aber Argument 2 hat Typ ‚int * '[-Wformat =]

im Fall werfen Sie diesen Wert auf ein char wird das Verhalten gut, aber auf eine ganze Zahl als Abguss eines Zeigertyps über die Umsetzung verlassen definiert werden, die Umsetzung definiert.

Nichtsdestoweniger macht das, was du machst, keinen Sinn, auch mit einer Besetzung, die es nicht tut.

+1

noch ein paar Ungenauigkeiten (was leicht über UB zu schließen ist): 1.) ascii ist nicht vorgeschrieben 2.) ein 'char' ist ** immer ** ein Byte, aber ein Byte könnte mehr als 8 Bits haben 3.) mit einer Umwandlung ist es nicht undefiniert, aber immer noch nicht besonders nützlich, weil das Ergebnis der Umwandlung eines Zeigers in einen Integer-Typ ist * Implementierung definiert * - immer noch upvoted, Erklärungen sind hilfreich! –

+0

@FelixPalmen: Vielen Dank für Ihre Erklärungen! –

+0

Die Antwort geht davon aus, dass 'int' und' int * 'die gleiche Größe haben und dass' int' und 'int *' über den gleichen Mechanismus an 'printf()' übergeben werden. Weder sind in C. – chux

Verwandte Themen