Kirjoittaja: Metabolix
Kirjoitettu: 24.06.2008 – 24.06.2008
Tagit: teksti, koodi näytille, vinkki
Matalan tason ohjelmoinnissa – ja miksei muuallakin – on usein tarpeen saada debuggausta varten binaaridataa ulos tarkasteltavassa muodossa, usein siis heksadesimaaliesityksenä. Tässäpä siihen valmis funktio, joka tulostaa datan hieman tyypillistä heksaeditoria jäljitellen: ensin heksamuotoinen data ja reunassa tekstimuotoinen versio. Riville tulostuu tässä versiossa oletusarvoisesti 16 tavua.
Funktion ensimmäinen parametri on tiedosto, johon tulostetaan. Standardivirta stdout ohjautuu yleensä ruudulle, samoin virhevirta stderr. Toinen parametri on osoitin tulostettavaan dataan ja kolmas datan pituus tavuina.
Esimerkkiohjelmassa todetaan wide char -tyypin ja tavallisen char-tyypin ero, joka toki riippuu myös käytettävästä järjestelmästä.
Dump-funktio tarvittavien otsikkojen kera
#include <ctype.h> #include <stdio.h> #define ROW_BYTES (16) #define NOT_GRAPH ('.') void dump(FILE *out, const void *ptr, int len) { const char *str = (const char *) ptr; int i, j; /* Koko data 16 tavun paloissa */ for (i = 0; i < len; i += ROW_BYTES) { /* Ensin haluttu tavumäärä heksana */ for (j = 0; j < ROW_BYTES && i + j < len; ++j) { fprintf(out, " %02x", (unsigned char)str[i+j]); } /* Jos dataa ei ollut riittävästi, täytetään loput tyhjällä */ for (; j < ROW_BYTES; ++j) { fprintf(out, " "); } /* Pieni rako */ fprintf(out, " "); /* Tulostetaan graafiset merkit ja muiden tilalle pisteitä */ for (j = 0; j < ROW_BYTES && i + j < len; ++j) { fputc((isgraph(str[i+j]) ? str[i+j] : NOT_GRAPH), out); } /* Rivin loppuun rivinvaihto */ fputc('\n', out); } }
Esimerkkiohjelma
#include <wchar.h> int main(void) { /* Tulostettavat muuttujat */ wchar_t wstr[] = L"teksti"; char str[] = "teksti"; int i = 1415926535; /* Dumppaillaan */ printf("wstr:\n"); dump(stdout, wstr, sizeof(wstr)); printf("str:\n"); dump(stdout, str, sizeof(str)); /* Huomaa & (osoite), kun ei ole taulukko! */ printf("i:\n"); dump(stdout, &i, sizeof(i)); return 0; }
Esimerkkituloste
wstr: 74 00 00 00 65 00 00 00 6b 00 00 00 73 00 00 00 t...e...k...s... 74 00 00 00 69 00 00 00 00 00 00 00 t...i....... str: 74 65 6b 73 74 69 00 teksti. i: 07 53 65 54 .SeT
Hieno vinkki varmasti tarpeen ohjelman kehitysvaiheessa. Hyvin kirjoitetut ja asialliset kommentit.
Mieleen tulee ainoastaan tuo #define rivi, joka kannataisi kait esitellä const int ROW_BYTES = 16; Kääntäjä osaisi purkaa tietotyypin ja varoitella väärästä käytöstä. Näin olen sen itselleni antanut kertoa.
Muuten todella mainota jälkeä.
Joo mutta eikös toi #define ole c:tä ja const int c++?
Ei, vaan #define on esikääntäjän komento ja const taas C-kielen avainsana. Näiden toimintaperiaate on täysin erilainen.
Tähän liittyen loisto utility:
man xxd