Speicheradresse positiver oder negativer Wert in c?

7

in c, ich habe versucht, die Adresse der Variablen und die Adresse einer Funktion auszudrucken. Ich habe einen negativen Wert, der andere ist ein positiver Wert. Meine Frage ist: Warum repräsentiert C nicht alle negativen oder alle positiven Werte?

Hier ist mein Code:

%Vor%

Hier ist das Ergebnis:

%Vor%     
root 06.11.2009, 18:29
quelle

10 Antworten

29

Speicheradressen sollten auf diese Weise nicht als vorzeichenbehaftete Ganzzahlen interpretiert werden. Das Vorzeichen der Zahl hängt vom höchsten gesetzten Bit ab (unter Annahme der Zweierkomplementdarstellung, die von der überwiegenden Mehrheit der derzeit verwendeten Systeme verwendet wird), so dass eine Speicheradresse über 0x80000000 auf einem 32-Bit-System negativ und ein Speicher ist Adresse unter 0x80000000 wird positiv sein. Das hat keine wirkliche Bedeutung.

Sie sollten Speicheradressen mit dem Modifizierer %p drucken. alternativ verwenden einige Benutzer %08x zum Drucken von Speicheradressen (oder %016llx auf 64-Bit-Systemen). Dies wird immer als hexadezimale Ganzzahl ohne Vorzeichen ausgegeben, was viel nützlicher ist als eine Ganzzahl mit Vorzeichen mit Vorzeichen.

%Vor%     
Adam Rosenfield 06.11.2009, 18:32
quelle
7

Um möglichst konform zu sein, übergeben Sie "% p" in der Formatzeichenfolge an printf() und das Argument an void* .

%Vor%

Zitat aus dem Standardentwurf (n1401.pdf)

%Vor%     
pmg 06.11.2009 18:43
quelle
6

Sie sollten den Zeigerformatierer übergeben:

%Vor%     
AraK 06.11.2009 18:32
quelle
4

Sie drucken im Dezimalformat. Wahrscheinlich möchten Sie den Speicherplatz hexadezimal ausgeben (mit "% p") (die meisten Speicheradressen werden per Konvention hexadezimal angezeigt).

    
Paul Sonier 06.11.2009 18:32
quelle
3

Weder ein Zeiger hat kein Vorzeichen, aber wenn er in eine vorzeichenbehaftete Ganzzahl konvertiert wird, kann er positiv oder negativ sein.

Übrigens führt die Übergabe eines Zeigers an printf mit einer Formatvariablen, die zum Drucken einer Ganzzahl entworfen wurde, zu undefiniertem Verhalten. Sie sollten immer explizit auf den richtigen Typ umwandeln, um ein nicht spezifiziertes oder implementierungsdefiniertes Verhalten zu erhalten (abhängig von der Besetzung).

    
Charles Bailey 06.11.2009 18:32
quelle
3

Zeiger sind keine Ganzzahlen mit Vorzeichen und sind viel mehr wie vorzeichenlose Ganzzahlen. Sie drucken sie jedoch so aus, als wären sie Ganzzahlen mit Vorzeichen. Auf einem 32-Bit-System gibt es mehrere Dinge, die wahrscheinlich 32 Bit lang sind: int , unsigned int , float und Zeiger. Sie können im Allgemeinen nicht sagen, welche diese nur sind, indem Sie sie betrachten, aber sie bedeuten alle verschiedene Dinge. (Als Experiment könnten Sie verschiedene Ganzzahlen übergeben und sie wie Floats drucken und umgekehrt: Es ist im Allgemeinen eine schlechte Übung, aber es kann Ihnen zeigen, dass verschiedene Datentypen unterschiedliche Dinge bedeuten.)

Funktionen, die eine variable Anzahl von Argumenten ("variadic" -Funktionen) annehmen, tun dies auf eine komplizierte Art und Weise. Insbesondere prüfen sie keine Argumenttypen. Sie können beliebige Argumente an printf() und ähnliche Funktionen übergeben, aber es ist Ihr Problem, sie mit dem Formatbezeichner zu vereinbaren. Dies bedeutet, dass die Funktion keine Möglichkeit hat, den Typ richtig zu machen (wie wenn Sie float an eine Funktion wie int foo(int) übergeben würden).

Das Übergeben falscher Argumenttypen führt zu einem nicht definierten Verhalten und führt besonders dann zu Problemen, wenn Sie Argumente mit der falschen Größe übergeben. Bei den meisten 64-Bit-Systemen sind Zeiger 64 Bits und int s sind 32.

Daher müssen Sie das Richtige in der Formatzeichenfolge verwenden. printf("%p", &a); gibt die Adresse von a als Zeiger aus, was Sie wollen. Der Standard erfordert etwas wie printf("%p", (void *)&a); , aber als praktische Sache ist das unnötig auf jedem Computer, den Sie wahrscheinlich jemals begegnen werden.

    
David Thornley 06.11.2009 19:07
quelle
1

Sie könnten auch printf("%p", &a) verwenden. %p ist der Zeigerformatspezifizierer, um den Wert eines Zeigers in einer implementierungsdefinierten Weise auszugeben. Praktisch gesprochen ist es ungefähr dasselbe wie% x, würde aber den Fall behandeln, bei dem ein Zeiger größer als ein int ist.

    
Jeff Paquette 06.11.2009 18:34
quelle
0

printf ist kein magisches Interpretationswerkzeug. Alles was es tut, wenn Sie es geben "% d" zeigt Ihnen, wie das Bitmuster, das in dieser Variable sitzt, wie eine Ganzzahl aussieht.

Warum einige Zeiger negativ und einige positiv sind, bedeutet nur, dass einige das höherwertige Bit gesetzt haben und andere nicht. Welche Adressen an Objekte vergeben werden, ist eigentlich nur das Geschäft Ihres Betriebssystems (normalerweise mit etwas Hardware-Hilfe). Die Programmiersprache hat kein echtes Mitspracherecht.

Wenn ich du wäre, würde ich Adressen nicht auf diese Weise ausdrucken. Wenn Sie wirklich das Bedürfnis haben, sie anzusehen, verwenden Sie "% x" anstelle von "% d". Das wird sie in Hex ausgeben, was es viel einfacher macht herauszufinden, welche Bits eingeschaltet sind und welche nicht. Im Allgemeinen werden Sie sich nur dann um Adressen kümmern, wenn sie 0 sind oder nicht, und wenn sie mit dem Wert einer anderen Adresse übereinstimmen.

    
T.E.D. 06.11.2009 18:56
quelle
0

Abgesehen von der Verwendung von %p können Sie auch in uintptr_t umwandeln, um sicherzustellen, dass Sie eine nicht erkannte Ganzzahl erhalten.

Verwenden Sie PRIuPTR (oder PRIXPTR für hex) form <inttypes.h> , um den korrekten Formatbezeichner zu erhalten:

%Vor%     
Christoph 06.11.2009 20:14
quelle
0

Verwenden Sie den folgenden Code:

%Vor%     
avd 06.11.2009 18:32
quelle

Tags und Links