Compiler "überspringt" Byte bei Initialisierung?!
-
Nicht erschrecken, Post lang aber nicht kompliziert!
Es scheint unmöglich, aber nachdem ich Stunden mit Debuggen verbracht habe, meine ich der Compiler veräppelt mich.Also: Es gibt da ein Tool, das generiert netterweise aus Fonts automatisch entsprechende arrays (nützlich für LCDs): http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/
Damit hab ich mir die ganze Palette an ASCII-Zeichen von '!' (0x21) bis '~' (0x7e) generiert, vgl. http://www.torsten-horn.de/techdocs/ascii.htm
Eine der generierten Strukturen sieht so aus:
typedef struct _font_char_info { std::uint8_t Charwidth; std::uint16_t Offset; // Das Offset ist interessant, es gibt den Byteabstand zwischen den Zeichen an }FONT_CHAR_INFO;
Das vom "The dot factory" generierte Array sieht wie folgt aus (nicht erschrecken):
const FONT_CHAR_INFO microsoftSansSerif_6ptDescriptors[] = { {1, 0}, // ! {3, 8}, // " {4, 16}, // # {4, 24}, // $ {7, 32}, // % {5, 40}, // & {1, 48}, // ' {2, 56}, // ( {2, 64}, // ) {3, 72}, // * {4, 80}, // + {1, 88}, // , {2, 96}, // - {1, 104}, // . {2, 112}, // / {4, 120}, // 0 {2, 128}, // 1 {4, 136}, // 2 {4, 144}, // 3 {4, 152}, // 4 {4, 160}, // 5 {4, 168}, // 6 {4, 176}, // 7 {4, 184}, // 8 {4, 192}, // 9 {1, 200}, // : {1, 208}, // ; {4, 216}, // < {4, 224}, // = {4, 232}, // > {4, 240}, // ? {8, 248}, // @ {5, 256}, // A {4, 264}, // B {5, 272}, // C {4, 280}, // D {4, 288}, // E {4, 296}, // F {6, 304}, // G {4, 312}, // H {1, 320}, // I {3, 328}, // J {4, 336}, // K {3, 344}, // L {5, 352}, // M {4, 360}, // N {6, 368}, // O {4, 376}, // P {6, 384}, // Q {4, 392}, // R {5, 400}, // S {5, 408}, // T {4, 416}, // U {5, 424}, // V {7, 432}, // W {5, 440}, // X {5, 448}, // Y {5, 456}, // Z {1, 464}, // [ {2, 472}, // \ {2, 480}, // ] {3, 488}, // ^ {4, 496}, // _ {2, 504}, // ` {4, 512}, // a {3, 520}, // b {4, 528}, // c {4, 536}, // d {4, 544}, // e {2, 552}, // f {4, 560}, // g {3, 568}, // h {1, 576}, // i {1, 584}, // j {3, 592}, // k {1, 600}, // l {5, 608}, // m {3, 616}, // n {4, 624}, // o {3, 632}, // p {4, 640}, // q {2, 648}, // r {4, 656}, // s {2, 664}, // t {3, 672}, // u {4, 680}, // v {6, 688}, // w {4, 696}, // x {4, 704}, // y {4, 712}, // z {2, 720}, // { {1, 728}, // | {2, 736}, // } {4, 744}, // ~ };
Jeder Buchstabe ist 8 Zeilen hoch, wird also in einem Byte gespeichert, wie z.B. nachfolgend das 'H':
// @312 'H' (4 pixels wide) 0x90, // # # 0x90, // # # 0xF0, // #### 0x90, // # # 0x90, // # # 0x90, // # # 0x00, // 0x00, //
Daher wird der Offset-Wert in microsoftSansSerif_6ptDescriptors auch brav jedes Mal um 8 Bytes erhöht. Wie man sieht ist das im Quelltext auch durchgängig korrekt.
Problem:
Ab dem Zeichen ']' (Offset 480) habe ich allerdings festgestellt, dass meine Zeichne-Routine immer das nachfolgende Zeichen (488. Nachfolgend statt 488 -> 496 usw.) gezeichnet hat. Dachte das hätte irgendwas mit std::uint16_t oder so zu tun. Dann hab ich mal das ganze Array in einer Datei gespeichert:ofstream file("dbg.txt"); for(int i=0; i<94; ++i) { file<<i<<'\t'<<(char)(i+0x21)<<'\t'<<microsoftSansSerif_6ptDescriptors[i].Offset<<endl; }
Ausgabe:
0 ! 0 1 " 8 2 # 16 3 $ 24 4 % 32 5 & 40 6 ' 48 7 ( 56 8 ) 64 9 * 72 10 + 80 11 , 88 12 - 96 13 . 104 14 / 112 15 0 120 16 1 128 17 2 136 18 3 144 19 4 152 20 5 160 21 6 168 22 7 176 23 8 184 24 9 192 25 : 200 26 ; 208 27 < 216 28 = 224 29 > 232 30 ? 240 31 @ 248 32 A 256 33 B 264 34 C 272 35 D 280 36 E 288 37 F 296 38 G 304 39 H 312 40 I 320 41 J 328 42 K 336 43 L 344 44 M 352 45 N 360 46 O 368 47 P 376 48 Q 384 49 R 392 50 S 400 51 T 408 52 U 416 53 V 424 54 W 432 55 X 440 56 Y 448 57 Z 456 58 [ 464 59 \ 472 60 ] 488 61 ^ 496 62 _ 504 63 ` 512 64 a 520 65 b 528 66 c 536 67 d 544 68 e 552 69 f 560 70 g 568 71 h 576 72 i 584 73 j 592 74 k 600 75 l 608 76 m 616 77 n 624 78 o 632 79 p 640 80 q 648 81 r 656 82 s 664 83 t 672 84 u 680 85 v 688 86 w 696 87 x 704 88 y 712 89 z 720 89 z 720 90 { 728 91 | 736 92 } 744 93 ~ 0
Der Compiler scheint also ab Zeile 60 bzw. Index 480 alles um +8 zu verschieben und für den letzten Array-Wert speichert er anstatt 744 einfach eine 0
Ich habe keine Ahnung, wer erklärt mir das Rätsel?
-
{2, 472}, // \
Mach den Backslash da am ende der Zeile weg, der escaped das nachfolgende newline, wodurch die nächste Zeile noch in diese Zeile mit rückt, allerdings im Kommentar steht und somit nicht berücksichtigt wird.
-
{2, 472}, // \
Das ist ein Kommentar mit anschließendem Zeilen(anti-)umbruch. Das heißt, die nächste Zeile gilt als Verlängerung dieser Zeile und somit als Teil des Kommentars.
edit: Zu langsam.
-
Sollte nicht jeder Compiler da eine Warnung ausspucken? gcc und clang zumindest tun das.
Stell deinen Compiler bitte richtig ein und aktiviere Warnungen!
-
Was für ein mieser Fehler... ich danke euch... Da sollte ich den Entwicklern des Tools eine Meldung machen, damit das Zeichen da nicht mehr automatisch generiert wird.
@bytheroot: Compiler ist der gcc und der hat bei mir nichts gemeldet (ich meine Default-Warnungen)
-
Bei gcc musst du mit
-Wall
kompilieren, sonst kriegst du nur sehr wenig Warnungen. Noch besser ist-Wall -Wextra -pedantic
.
-
AbsolutUnklar schrieb:
@bytheroot: Compiler ist der gcc und der hat bei mir nichts gemeldet (ich meine Default-Warnungen)
Default ist halt nur bei wirklich krassen Fehlern zu warnen. Mach mindestens "Wall" an! Ich mag auch "Wextra", wobei das aber etwas kontrovers ist, da man manche der dortigen Warnungen eher als stilistische Zwänge bewerten kann.
-
Was für ein mieser Fehler... ich danke euch... Da sollte ich den Entwicklern des Tools eine Meldung machen, damit das Zeichen da nicht mehr automatisch generiert wird.
Nicht ganz. Sag ihnen einfach sie sollen entweder /* */ Kommentare verwenden oder ein zusätzliches Newline am Ende jeder Kommentarzeile im entsprechenden Abschnitt einfügen (wobei letzteres mit einigen IDEs ggf. nicht funktioniert).
-
Arcoth schrieb:
Was für ein mieser Fehler... ich danke euch... Da sollte ich den Entwicklern des Tools eine Meldung machen, damit das Zeichen da nicht mehr automatisch generiert wird.
Nicht ganz. Sag ihnen einfach sie sollen entweder /* */ Kommentare verwenden oder ein zusätzliches Newline am Ende jeder Kommentarzeile im entsprechenden Abschnitt einfügen (wobei letzteres mit einigen IDEs ggf. nicht funktioniert).
Ich hoffe mal, dass die Entwickler selber auf eine passende Lösung kommen. Wobei /* */ Kommentare aber auch doof sind. Ich würde einfach alles in Anführungsstriche setzen. Das Zeichen heißt in C++ schließlich
'\'
, nicht\
.
-
SeppJ schrieb:
Ich würde einfach alles in Anführungsstriche setzen.
+1
SeppJ schrieb:
Das Zeichen heißt in C++ schließlich
'\'
, nicht\
.Das Zeichen heisst in C++ eigentlich
'\\'
. (Oder meinst du jetzt was anderes?)
Und das wäre mir ehrlich gesagt egal. Es in einfache Hochkomma zu setzen sieht einfach halbwegs "vernünftig" aus, und verhindert mMn. viel effektiver als ein zusätzlicher Zeilenumbruch (wo schnell jemand auf die Idee kommen könnte den wegzumachen) dass Probleme auftreten.