Forum: PC-Programmierung C, VS, Struct


von Anonymous U. (gastt)


Lesenswert?

Hallo allerseits,

ich versuche seit Stunden Daten von einem Array als Bitmap zu speichern. 
Jetzt bin ich drauf gekommen, dass der Header nicht stimmt. Ich habe den 
Header in 2 structs aufgeteilt. Dieses Padding hab ich schon 
ausgeschaltet (muss man erst mal drauf kommen).
In dem struct sind verschiedene Formate nacheinander abgespeichert. Mein 
Plan war (auch in vielen Beilpielen ist das so realisiert), dass dieses 
Struct dann einfach byte für byte in die Datei geschrieben wird. Nun ist 
es so: struct bmpheader.widthbmp = 640. Wenn ich bmpheader.widthbmp 
ausgebe, so erhalte ich 640. Allerdings wenn ich den Speicherbereich von 
bmpheader.widthbmp auslese kommt Murks raus und ich verstehe nicht 
warum. Warum ist das so und wie kann ich das Problem lösen?
1
typedef struct fileheader{
2
  char filetype1, filetype2;
3
  DWORD sizefile;
4
  DWORD reserved = 0;
5
  DWORD offsetdata = 54;
6
};
7
typedef struct bmpheader{
8
  DWORD sizeheader = 40;
9
  DWORD widthbmp;
10
  DWORD heigthbmp;
11
  WORD planes = 1;
12
  WORD colbits = 8;
13
  DWORD compression = 0;
14
  DWORD sizedata;
15
  DWORD pixpmx = 0;
16
  DWORD pixpmy = 0;
17
  DWORD coltbl1 = 0;
18
  DWORD coltbl2 = 0;
19
};
20
21
void bmpout(char *inputarr, struct ginterface_2d_1d *settings){
22
23
  /*Bitmapfileheader*/
24
  fileheader fheader;
25
  fheader.sizefile = (settings->resolutionx*settings->resolutiony)+sizeof(fileheader)+sizeof(bmpheader);
26
  fheader.filetype1 = 'B'; fheader.filetype2 = 'M';
27
  /*Bitmapinfoheader*/
28
  bmpheader bheader;
29
  bheader.colbits = 8;
30
  bheader.heigthbmp = settings->resolutiony;
31
  bheader.sizedata = settings->resolutionx*settings->resolutiony;
32
  bheader.widthbmp = 256;// (DWORD)settings->resolutionx;
33
34
  std::ofstream bmpdata("test.bmp", std::ios::out | std::ios::binary);
35
  bmpdata.write((char*)&fheader, sizeof(fheader));
36
  bmpdata.write((char*)&bheader, sizeof(bheader));
37
38
  char test[60] = { 0 };
39
  for (int i = 0; i != 14; ++i){
40
    test[i] = *((char*)&bheader + i);
41
    for (int ii = 7; ii >= 0; --ii){
42
      if ((1 << ii)&test[i])
43
        printf("1");
44
      else
45
        printf("0");
46
    }
47
    printf(" | %8x\n", test[i]);
48
  }
49
  printf("\n");
50
51
  int zähler = 0;  //#
52
  char b = 0x01;  //#
53
  for (int i = 0; i != settings->resolutiony; i++){
54
    for (int ii = 0; ii != settings->resolutionx; ii++) {
55
      bmpdata.write(&b, 1);  //#
56
      //bmpdata.write(&pic_diagram[ii][i], 1);
57
      zähler++;  //#
58
      continue;
59
    }
60
  }
61
  bmpdata.close();
62
63
  //#
64
  printf("Headersize: %d & %d\n", sizeof(fheader), sizeof(bheader));
65
  printf("dazasize: %d\n\n", zähler);
66
  printf("bmp headerdata:\n|");
67
  for (int i = 0; i != 10; i++){
68
    printf(" %ld |", *((long *)&bheader + i));
69
  }
70
  scanf("%c", &b);
71
  //printf("%s", ginterface.pic_diagramm);
72
}

von Michael S. (schiko)


Lesenswert?

Dreh den Spieß mal um:
Nehme ein x-beliebiges Malprogramm, erzeuge Dir 'ne Bitmap
wie Du sie wünscht, und schau's Dir binär an.

von Anonymous U. (gastt)


Lesenswert?

Michael Schikora schrieb:
> Dreh den Spieß mal um:
> Nehme ein x-beliebiges Malprogramm, erzeuge Dir 'ne Bitmap
> wie Du sie wünscht, und schau's Dir binär an.

Ja hab ich gemacht: Es liegt an dem Struct.

Beispiel:
1
struct test{
2
word a;
3
dword b;
4
dword c;
5
};
6
7
struct test newtest;
8
newtest.a = 10;
9
newtest.b = 20;
10
newtest.c = 600;
11
12
printf("%i", newtest.c);

Als Ausgabe erhalte ich 600. Würde passen. Und nun:
1
printf("%x,%x", *((char*)&newtest+2+4+2),*((char*)&newtest+2+4+3));

Da kommt als Ausgabe Murks. Aber eigentlich erwarte ich 600 in 
hexadezimal!!!

: Bearbeitet durch User
von DirkB (Gast)


Lesenswert?

Du musst erst newtest in einen char* casten und dann dein Offset darauf 
addieren.
Dazu reicht es etwas anders zu klammern.

von Anonymous U. (gastt)


Lesenswert?

DirkB schrieb:
> Du musst erst newtest in einen char* casten und dann dein Offset darauf
> addieren.
> Dazu reicht es etwas anders zu klammern.

Wie macht man sowas?

von Michael S. (schiko)


Lesenswert?

ich würde "0,0" erwarten auf nem x86 (Little Endian)

von Anonymous U. (gastt)


Lesenswert?

Michael Schikora schrieb:
> ich würde "0,0" erwarten auf nem x86 (Little Endian)

Ja stimmt natürlich. In dem Beispiel müssen 2 weniger addiert werden:
1
printf("%x,%x", *((char*)&newtest+2+4+1),*((char*)&newtest+2+4+0));

: Bearbeitet durch User
von Michael S. (schiko)


Lesenswert?

Anonymous User schrieb:
> Michael Schikora schrieb:
>> ich würde "0,0" erwarten auf nem x86 (Little Endian)
>
> Ja stimmt natürlich. In dem Beispiel müssen 2 weniger addiert werden:
>
1
> printf("%x,%x", *((char*)&newtest+2+4+1),*((char*)&newtest+2+4+0));
2
>

char* p = (char*)&newtest;
printf("%02X ", *(p + ..)  );
..
.

von Anonymous U. (gastt)


Lesenswert?

Hmm, anscheinend kommt bei mir doch kein direkter Murks raus... 
printf("%x") gibt bei größeren zahlen als 255 grundsätzlich erstmal 
ffffff aus. Der Rest dahinter passt: ffffff80, und der nächste hex-Wert 
ist 02, also 640. Das würde passen. Was ist hier verkehrt?

von Michael S. (schiko)


Lesenswert?

Anonymous User schrieb:

> [..]  Was ist hier verkehrt?

Du hast noch kein Bild mit Paint gemalt und verglichen.

von Arc N. (arc)


Lesenswert?


von Anonymous U. (gastt)


Lesenswert?

Arc Net schrieb:
> Wenn C und VS im Betreff steht, warum dann nicht die von MS
> bereitgestellten Strukturen und Funktionen benutzen?

Ich wills ja verstehen warums nicht funktioniert.


So, ich glaub mich trifft der Schlag: mit folgendem cast geht das 
printf: (unsigned char*). Ich dachte damit wird nur eingestellt um wie 
viele bytes der pointer bei ++ weiterspringt. Was macht der Compiler da 
schon wieder im Hintergrund für Sachen???

Das Problem ist nun, dass ofstream nur mit zeiger vom typ (char*) 
umgehen kann und nicht mit (unsigned char*). Was kann ich noch tun?

von Anonymous U. (gastt)


Lesenswert?

Hier nochmal zum Verdeutlichen:

  printf("%x\n", ((char*)&bheader + 4));
  printf("%x\n", ((unsigned char*)&bheader + 4));
  printf("%x\n", *((char*)&bheader + 4));
  printf("%x\n", *((unsigned char*)&bheader + 4));

Ausgabe:

20ad6c
20ad6c
ffffff80
80

von Rolf M. (rmagnus)


Lesenswert?

Anonymous User schrieb:
> Was macht der Compiler da schon wieder im Hintergrund für Sachen???

Nennt sich Integer Promotion.

von Anonymous U. (gastt)


Lesenswert?

Rolf Magnus schrieb:
> Nennt sich Integer Promotion.

Ah, da kennt sich wer aus. Das Stichwort hätt ich in 100 Jahren nicht 
gefunden.

Und schon wieder ein Grund warum ich am liebsten bei Assembler bleiben 
würde ;-)

von Anonymous U. (gastt)


Lesenswert?


Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.