Forum: Compiler & IDEs uint64_t und Bits 33-64 lesen bzw. setzen


von Gast (Gast)


Lesenswert?

Hallo,

ich habe ein Problem mit dem uint64_t Datentyp. Mein Testprogramm sieht 
so aus:
1
#include <inttypes.>
2
#include <stdio.h>
3
4
#define SET_BIT64(port, bit)   ((port) = (uint64_t)((uint64_t)(port) | (uint64_t)(1ULL << (bit))))
5
#define IS_BIT_SET64(port, bit) ((uint64_t)((uint64_t)(port) & (uint64_t)(1ULL << (bit))) ? 1 : 0)
6
7
void dbg(unsigned long long b) {
8
  for (int i = 0; i < 64; ++i) {
9
    if (IS_BIT_SET64(b, i)) {
10
      printf("X");
11
    } else {
12
      printf(".");
13
    }
14
  }
15
  printf("\n");
16
}
17
18
void test() {
19
  unsigned long long test;
20
21
  for (int i = 0; i < 64; ++i) {
22
    SET_BIT64(test, i);
23
    dbg(test);
24
  }
25
}
26
27
int main(int argc, char **argv) {
28
  test();
29
  return 0;
30
}

Es werden nur die Bits 0-31 richtig gesetzt bzw. ausgelesen. Die Bits 
33-64 funktionieren nicht. Woran könnte das liegen?

Vielen Dank schon einmal für eine hilfreiche Antwort.

von Karl H. (kbuchegg)


Lesenswert?

Ich würde jetzt mal mindestens die Hälfte der casts aus den Makros 
rauswerfen und mir die Fehlermeldungen bzw. Warnungen des Compilers 
genau(!) ansehen. Im höchsten Warninglevel.
Einige der Casts sind redundant. Wenn du casten muss, dann fang 'innen' 
in den entsprechenden Ausdrücken an. Dann ergibt sich auch der Rest 
automatisch, weil der Compiler nie von sich aus einen größeren Datentyp 
auf einen kleineren zurückcastet. So ein Cast-Rundumschlag, wie du ihn 
veranstaltet hast, ist meistens kontraproduktiv und verdeckt oft 
essentiell wichtige Warnungen.

Edit:
Mit deinen Datentypen sollte in den Makros eigentlich überhaupt kein 
Cast notwendig sein. Das (korretkerweise benutzte) 1ULL sollte 
eigentlich schon vollständig ausreichen um die Ausdrücke komplett auf 
unsigned long long zu zwingen.

von Gast (Gast)


Lesenswert?

Oh, danke für die Antwort. Wie immer saß das Problem nicht im, sondern 
vor dem Computer. Ich hatte ein Problem mit dem Makefile, das den Code 
nicht neu uebersetzt hat. Nach einem "make clean" und einem neuen Build 
hat es so funktioniert, wie ich es erwartet habe. shame on me

von Peter D. (peda)


Lesenswert?

Wenn möglich, sollte man 64Bit nicht verwenden.

Der AVR-GCC hat keine optimierte 64Bit-Library, sondern macht das 
äußerst umständlich.
Ich würde micht nicht wundern, wenn Dein Mini-Programm allein schon 8kB 
Code erzeugt.

Deutlich schnelleren und kleineren Code erreichst Du mit einem Array aus 
kleineren Typen, z.B.:
1
uint8_t var64[8];
2
3
4
void set64bit( uint8_t *p, uint8_t num )
5
{
6
  *(p+(num>>3)) |= 1 << (num & 0x7);
7
}
8
9
uint8_t test64bit( uint8_t *p, uint8_t num )
10
{
11
  return *(p+(num>>3)) & (1 << (num & 0x7));
12
}


Peter

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Von avr-gcc war zwar nix zu lesen, aber wenn's darum geht, hat Peter 
recht. 64-Bit Typen werden im AVR-Backend von GCC nicht unterstützt, 
sondern werden im maschinenunanhängigen Teil zu 8-Bit Operationen 
ausgetextet.

Des weiteren ist anzumerken, daß in test() die Variable test (sic!) 
nicht initialisiert wird. Obwohl nachfolgend alle Bits gesetzt werden, 
würd ich nicht dafür garantieren, daß ein optimierender GCC hier immer 
den erwarteten Code macht.

Johann

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.