uint64_t und Bits 33-64 lesen bzw. setzen

Gast #1451690
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.
#1451734
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.
#1451778
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
Persönliche Seite #1451994
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren