Wie drucke ich den Speicherinhalt einer Variablen in C aus?

Lesezeit: 9 Minuten

Angenommen, ich mache a

double d = 234.5;

Ich möchte den Speicherinhalt von sehen d [the whole 8 bytes]

Wie mache ich das?

  • In welcher Form willst du es sehen?

    – Danben

    4. März 2010 um 4:38 Uhr

  • warum glauben Sie, dass es acht Bytes sind?

    – Martin York

    4. März 2010 um 4:40 Uhr

  • Ich glaube, Schwimmer sind normalerweise vier Bytes und Doubles sind normalerweise acht Byte.

    – Dolph

    4. März 2010 um 4:42 Uhr

  • Das ist die Implementierung definiert.

    Benutzer1831086

    4. März 2010 um 4:44 Uhr

  • Seine Größe (doppelt), die von der Hardware und den Compiler-Optionen abhängt.

    – Martin York

    4. März 2010 um 4:44 Uhr

Benutzer-Avatar
Café

unsigned char *p = (unsigned char *)&d;
int i;

for (i = 0; i < sizeof d; i++)
    printf("%02x ", p[i]);

  • @Craig: sizeof d ist richtig, ich weiß nicht, warum du es geändert hast sizeof(d) (das geht auch, aber viele mögen es sizeof d Wenn d ist kein Typ).

    – Alok Singhal

    4. März 2010 um 5:40 Uhr


  • Einverstanden – ich halte lieber klar, dass es sich um einen Operator handelt, nicht um eine Funktion (das tue ich nicht return(x);entweder)

    – Café

    4. März 2010 um 5:59 Uhr


  • Es ist einfacher, einfach immer Klammern zu verwenden, um keine speichern zu müssen mehr Ding in der grauen Substanz oben 🙂 I tun Bevorzugen Sie die Verwendung einer Variablen anstelle eines Typs, falls sich der Typ der Variablen jemals ändert, sodass ich nicht so viel Code ändern muss.

    – paxdiablo

    4. März 2010 um 6:09 Uhr


double d = 234.5;

/* 1. use a union */
union u {
    double d;
    unsigned char c[sizeof(double)];
};
union u tmp;
size_t i;
tmp.d = d;
for (i=0; i < sizeof(double); ++i)
    printf("%02x\n", tmp.c[i]);

/* 2. memcpy */
unsigned char data[sizeof d];
size_t i;
memcpy(data, &d, sizeof d);
for (i=0; i < sizeof d; ++i)
    printf("%02x\n", data[i]);

/* 3. Use a pointer to an unsigned char to examine the bytes */
unsigned char *p = (unsigned char *)&d;
size_t i;
for (i=0; i < sizeof d; ++i)
    printf("%02x\n", p[i]);

Alle Methoden zeigen Ihnen die Bytes – aber die gleichen double value kann die Bytes auf verschiedenen Systemen unterschiedlich ausgeben, z. B. aufgrund unterschiedlicher Kodierungen (selten) oder unterschiedlicher Endianness.

  • Ich hätte persönlich einen Zeiger verwendet, aber eine Gewerkschaft ist imo noch besser. Schön. Ich neige dazu, es zu vergessen.

    – Xorlev

    4. März 2010 um 5:38 Uhr

  • Xorlev: Technisch gesehen funktioniert die Union-Methode nicht garantiert, während die anderen beiden Methoden funktionieren.

    – Café

    16. März 2010 um 22:56 Uhr

  • @caf: warum sagst du, dass die gewerkschaftsmethode nicht garantiert funktioniert? Solange man nutzt unsigned char Array in der Union, sollte es funktionieren.

    – Alok Singhal

    16. März 2010 um 23:06 Uhr

  • Anhang J des C-Standards listet “Der Wert eines anderen Gewerkschaftsmitglieds als das zuletzt gespeicherte” als “nicht spezifiziert” auf, und daran habe ich gedacht. Ich glaube jedoch nicht, dass der Anhang normativ ist, und ich kann keine normative Referenz finden, die dasselbe sagt, sodass der Anhang möglicherweise fehlerhaft ist.

    – Café

    16. März 2010 um 23:36 Uhr

  • @café, danke. In Fußnote 82 heißt es: Wenn das für den Zugriff auf den Inhalt eines Union-Objekts verwendete Element nicht dasselbe ist wie das Element, das zuletzt zum Speichern eines Werts im Objekt verwendet wurde, wird der entsprechende Teil der Objektdarstellung des Werts als Objektdarstellung in neu interpretiert den neuen Typ, wie in 6.2.6 beschrieben (ein Vorgang, der manchmal als “Typ-Wortspiel” bezeichnet wird). Dies könnte eine Fallendarstellung sein. Aber auch das ist nicht normativ. Nachdem ich viele Nachrichten auf comp.lang.c gelesen habe, scheint es, als würden die Leute dort diese spezielle Methode (unsigned char in einer Gewerkschaft) ist erlaubt.

    – Alok Singhal

    17. März 2010 um 0:12 Uhr

Benutzer-Avatar
paxdiablo

Mit freundlicher Genehmigung meiner Bibliothek mit nützlichen Snippets, hier ist eine Lösung in C, komplett mit Testrahmen und Bereitstellung von Hex- und ASCII-Daten:

#include <stdio.h>

void hexDump (char *desc, void *addr, int len) {
    int i;
    unsigned char buff[17];       // stores the ASCII data
    unsigned char *pc = addr;     // cast to make the code cleaner.

    // Output description if given.

    if (desc != NULL)
        printf ("%s:\n", desc);

    // Process every byte in the data.

    for (i = 0; i < len; i++) {
        // Multiple of 16 means new line (with line offset).

        if ((i % 16) == 0) {
            // Just don't print ASCII for the zeroth line.

            if (i != 0)
                printf ("  %s\n", buff);

            // Output the offset.

            printf ("  %04x ", i);
        }

        // Now the hex code for the specific character.

        printf (" %02x", pc[i]);

        // And store a printable ASCII character for later.

        if ((pc[i] < 0x20) || (pc[i] > 0x7e))
            buff[i % 16] = '.';
        else
            buff[i % 16] = pc[i];
        buff[(i % 16) + 1] = '\0';
    }

    // Pad out last line if not exactly 16 characters.

    while ((i % 16) != 0) {
        printf ("   ");
        i++;
    }

    // And print the final ASCII bit.

    printf ("  %s\n", buff);
}

int main (int argc, char *argv[]) {
    double d1 = 234.5;
    char s1[] = "a 15char string";
    char s2[] = "This is a slightly longer string";
    hexDump ("d1", &d1, sizeof d1);
    hexDump ("s1", &s1, sizeof s1);
    hexDump ("s2", &s2, sizeof s2);
    return 0;
}

Die Ausgabe auf meinem System ist:

d1:
  0000  00 00 00 00 00 50 6d 40                          .....Pm@
s1:
  0000  61 20 31 35 63 68 61 72 20 73 74 72 69 6e 67 00  a 15char string.
s2:
  0000  54 68 69 73 20 69 73 20 61 20 73 6c 69 67 68 74  This is a slight
  0010  6c 79 20 6c 6f 6e 67 65 72 20 73 74 72 69 6e 67  ly longer string
  0020  00                                               .

Da diese Frage auch mit C++ gekennzeichnet ist, finden Sie hier eine Iostream-Version zum Vergleich. Auch wenn Sie kein besonderer Fan von iostreams sind, passt es trotzdem, wenn Sie sie bereits verwenden. Nutzen können hexdump(any_obj) ist auch nett, aber kann natürlich nur mit einer delegierenden Funktionsvorlage ähnlich dem ctor gemacht werden.

#include <iomanip>
#include <ostream>
#include <string>

struct hexdump {
  void const* data;
  int len;

  hexdump(void const* data, int len) : data(data), len(len) {}

  template<class T>
  hexdump(T const& v) : data(&v), len(sizeof v) {}

  friend
  std::ostream& operator<<(std::ostream& s, hexdump const& v) {
    // don't change formatting for s
    std::ostream out (s.rdbuf());
    out << std::hex << std::setfill('0');

    unsigned char const* pc = reinterpret_cast<unsigned char const*>(v.data);

    std::string buf;
    buf.reserve(17); // premature optimization

    int i;
    for (i = 0; i < v.len; ++i, ++pc) {
      if ((i % 16) == 0) {
        if (i) {
          out << "  " << buf << '\n';
          buf.clear();
        }
        out << "  " << std::setw(4) << i << ' ';
      }

      out << ' ' << std::setw(2) << unsigned(*pc);
      buf += (0x20 <= *pc && *pc <= 0x7e) ? *pc : '.';
    }
    if (i % 16) {
      char const* spaces16x3 = "                                                ";
      out << &spaces16x3[3 * (i % 16)];
    }
    out << "  " << buf << '\n';

    return s;
  }
};

int main() {
  std::cout << "double:\n" << hexdump(234.5);
  std::cout << "string 1:\n" << hexdump("a 15char string");
  std::cout << "string 2:\n" << hexdump("This is a slightly longer string");

  return 0;
}

  • Da diese Frage auch mit C++ getaggt ist, iostream-Version zum Vergleich: codepad.org/trVz9mlQ. Ich bin kein besonderer Fan von iostreams, aber es passt, wenn Sie sie bereits verwenden. Nutzen können hexdump(any_obj) ist auch nett (aber kann natürlich nur mit einer delegierenden Funktionsvorlage ähnlich diesem ctor gemacht werden).

    Roger Pate

    4. März 2010 um 7:44 Uhr

  • @Roger, ich wollte diesen Code in diese Antwort aufnehmen (natürlich mit Namensnennung und dem Vorschlag, dass ich ihn aus meiner entfernen würde, wenn Sie Ihre eigene Antwort posten würden). Das liegt daran, dass ich es vorziehe, dass SO auch dann noch nützlich ist, wenn alle anderen Sites auf dem Planeten (wie Codepad) verschwunden sind. Als ich jedoch Ihre Urheberrechtsrichtlinie auf Ihrer SO-Benutzerseite sah, musste ich innehalten – niemand kann Ihren Code verwenden, wenn Sie die Urheberrechte wahren, er ist außer für Bildungszwecke nutzlos. Aus diesem Grund würde ich es vorziehen, wenn Sie es als richtige Antwort posten und nicht als Kommentar mit einem Link, aber es liegt ganz bei Ihnen.

    – paxdiablo

    4. März 2010 um 8:53 Uhr

  • Ich dachte, dies bezog sich mehr auf Ihre Antwort, als eine separate Antwort wert wäre, und der Platz für Kommentare ist begrenzt, also habe ich nur reflexartig nach Codepad gegriffen. Ich werde die Frage bearbeiten, um sie aufzunehmen, und dann bin ich derjenige, der sie unter die Lizenz von SO stellt. Bearbeiten Sie nach Belieben. — FWIW, obwohl ich denke, dass Sie es jetzt erkennen, wiederhole ich nur “den Standard”, indem ich in meiner Biografie erwähne, dass an anderer Stelle geposteter Code nicht von SOs Lizenz abgedeckt ist, aber ich hatte beabsichtigt, dass es mehr um länger geht, weniger trivialer Code als etwa kurze Codepad.org-Einfügungen.

    Roger Pate

    4. März 2010 um 9:07 Uhr


Wenn Sie dies von gdb aus anzeigen möchten, können Sie Folgendes ausgeben:

x /gx d

Das g druckt den Wert als Riese (8 Bytes)

Benutzer-Avatar
sganesh

Wenn Sie die doppelten Werte in Bits drucken möchten, versuchen Sie dies. Ich habe es mit dem Float-Wert versucht. Wenn Sie das geändert haben, können Sie den doppelten Wert in 64 Bit anzeigen.

#include <stdio.h>

int main (void)
{
        float f = 10.0f;

        struct Float {
                unsigned char bit01:1;
                unsigned char bit02:1;
                unsigned char bit03:1;
                unsigned char bit04:1;
                unsigned char bit05:1;
                unsigned char bit06:1;
                unsigned char bit07:1;
                unsigned char bit08:1;
                unsigned char bit09:1;
                unsigned char bit10:1;
                unsigned char bit11:1;
                unsigned char bit12:1;
                unsigned char bit13:1;
                unsigned char bit14:1;
                unsigned char bit15:1;
                unsigned char bit16:1;
                unsigned char bit17:1;
                unsigned char bit18:1;
                unsigned char bit19:1;
                unsigned char bit20:1;
                unsigned char bit21:1;
                unsigned char bit22:1;
                unsigned char bit23:1;
                unsigned char bit24:1;
                unsigned char bit25:1;
                unsigned char bit26:1;
                unsigned char bit27:1;
                unsigned char bit28:1;
                unsigned char bit29:1;
                unsigned char bit30:1;
                unsigned char bit31:1;
                unsigned char bit32:1;
        };

        struct Float *F;

        F = (struct Float *) &f;

        printf("\nMSB -->1 bit for sign bit; 8 bit for exponent; 23 bit for mantisa<-- LSB\n");
        printf("%d ", F->bit32);
        printf("%d", F->bit31);
        printf("%d", F->bit30);
        printf("%d", F->bit29);
        printf("%d", F->bit28);
        printf("%d", F->bit27);
        printf("%d", F->bit26);
        printf("%d", F->bit25);
        printf("%d ", F->bit24);
        printf("%d", F->bit23);
        printf("%d", F->bit22);
        printf("%d", F->bit21);
        printf("%d", F->bit20);
        printf("%d", F->bit19);
        printf("%d", F->bit18);
        printf("%d", F->bit17);
        printf("%d", F->bit16);
        printf("%d", F->bit15);
        printf("%d", F->bit14);
        printf("%d", F->bit13);
        printf("%d", F->bit12);
        printf("%d", F->bit11);
        printf("%d", F->bit10);
        printf("%d", F->bit09);
        printf("%d", F->bit08);
        printf("%d", F->bit07);
        printf("%d", F->bit06);
        printf("%d", F->bit05);
        printf("%d", F->bit04);
        printf("%d", F->bit03);
        printf("%d", F->bit02);
        printf("%d\n", F->bit01);
}

Versuchen

union Plop
{
    double   value;
    char     data[sizeof(double)];
};

Plop print;
print.value = 234.5;

std::copy(print.data,print.data+sizeof(double),std::ostream_iterator<int>(std::cout)," ");
std::cout << std::endl;

Benutzer-Avatar
Arun

Haben Sie versucht, die Adresse von zu übernehmen? d und drucken sizeof( d ) Bytes ab dieser Adresse?

1369550cookie-checkWie drucke ich den Speicherinhalt einer Variablen in C aus?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy