Hallo, das Bit-Shiften funktioniert nicht. Die oberen 32 Bit sind immer 0. uint64_t ullValue = 0xFFFFFFFF; uint8_t ucValue = (uint8_t)((uint64_t)(ullValue >> 40)); Ergebnis: ucValue = 0 Wie kann ich auf die oberen 32 Bit zugreifen ? Gruß Peter
Peter schrieb: > Hallo, > > das Bit-Shiften funktioniert nicht. Doch, tut es. Peter schrieb: > 32 > … > ullValue >> 40 Denk da nochmal kurz drüber nach. > Ergebnis: ucValue = 0 Das ist richtig. Oliver
:
Bearbeitet durch User
Peter schrieb: > Hallo, > > das Bit-Shiften funktioniert nicht. Die oberen 32 Bit sind immer 0. > > uint64_t ullValue = 0xFFFFFFFF; > uint8_t ucValue = (uint8_t)((uint64_t)(ullValue >> 40)); > > Ergebnis: ucValue = 0 > > Wie kann ich auf die oberen 32 Bit zugreifen ? > > Gruß Peter Ist ja auch richtig, wenn man den uint64_t nur zur Hälfte befüllt. Versuchs mal mit 0xFFFFFFFFFFFFFFFF... Ach, was solls:
1 | uint64_t ullValue = 0xFFFFFFFFFFFFFFFF; |
2 | uint8_t byteArray[8]; |
3 | |
4 | for (int i = 0; i < 8; i++) |
5 | {
|
6 | byteArray[i] = (uint8_t)(ullValue >> (8 * i)); |
7 | printf("%d. 0x%x\n", i + 1, byteArray[i]); |
8 | }
|
:
Bearbeitet durch User
Oliver S. schrieb: > Denk da nochmal kurz drüber nach. Tim T. schrieb: > Ist ja auch richtig, wenn man den uint64_t nur zur Hälfte befüllt. OMG! - Ich stelle fest: 8 x F != 8 Bytes !!!! Ich mach da schon ne Stunde rum :) DANKE an Euch. Gruß Peter
Tim T. schrieb: > uint64_t ullValue = 0xFFFFFFFFFFFFFFFF; Man kann auch einfacher schreiben:
1 | uint64_t ullValue = -1; |
Als Zuweisung sind signed Werte erlaubt. Sie werden dann in den entsprechenden Binärwert konvertiert.
Das wurde erst nach Peters C-Sozialisierung erfunden... Oliver
Oliver S. schrieb: > Das wurde erst nach Peters C-Sozialisierung erfunden... wobei, wenn ich alle Bits gesetzt haben möchte, würde ich wahrscheinlich statt
1 | UINT64_MAX
|
lieber
1 | ~0 |
schreiben.
Böse Falle. Wenn schon, dann ~0ULL. Ansonsten kann auf Systemen, bei denen ein Integer nicht 64 Bit breit ist, einen kleinerer Wert hinterlegt werden.
:
Bearbeitet durch User
Walter T. schrieb: > Ich weiß > gerade nur nicht, warum. Zumindest bei der Erzeugnung eines > 32-Bit-Binaries auf einem 64-Bit-System. Weil der Compiler "annimmt", dass es sich bei "0" um eine Zahl aus dem Zielzahlenbereich "uint64_t" handelt?! Peter D. schrieb: > Man kann auch einfacher schreiben:uint64_t ullValue = -1; > Als Zuweisung sind signed Werte erlaubt. Sie werden dann in den > entsprechenden Binärwert konvertiert. Da würde ich vermuten, dass ein Warning erzeugt wird (zumindest meckert "mein" Keil rum: "warning: #68-D: integer conversion resulted in a change of sign"). Ein Cast sollte reichen.
Ich habe meinen vorheriges Edit gelöscht, weil mein vorheriger Einwand gegenstandslos geworden war. Deswegen passt das Zitat nicht mehr zu meinem Beitrag. Sinngemäß stand da: "Nanu, uint64_t a = ~0; funktiert ja." STK500-Besitzer schrieb: > Weil der Compiler "annimmt", dass es sich bei "0" um eine Zahl aus dem > Zielzahlenbereich "uint64_t" handelt?! Nein, es liegt daran, dass mein Build-Prozeß eine 64-Bit-EXE erzeugt hat. Ich hatte es nur vergessen, dass ich vor längerer Zeit umgestellt habe.
:
Bearbeitet durch User
Walter T. schrieb: > Wenn schon, dann ~0ULL. Aber ist uint64_t denn immer unsigned long long? Da doch lieber
1 | UINT64_MAX
|
(in C) oder
1 | std::numeric_limits<std::uint64_t>::max() |
(C++). Es ginge auch noch
1 | ((uint64_t) ~((uint64_t) 0)) |
in C bzw.
1 | static_cast<std::uint64_t> (~std::uint64_t { 0 }) |
in C++, aber schön ist anders. Der äußere Cast ist eventuell je nach Plattform nötig um Integer Promotion zu umgehen.
Walter T. schrieb: in, es liegt daran, dass mein Build-Prozeß eine 64-Bit-EXE erzeugt > hat. Ich hatte es nur vergessen, dass ich vor längerer Zeit umgestellt > habe. Nein. Das Literal 0 hat den Typ int, ~0 invertiert die Bits des int, das Ergebnis ist wieder der Typ int (Promotionsregeln) und hat den Wert -1. Mit -1 wird dann der uint64_t initialisiert, und dabei wird auf uint64_t konvertiert.
:
Bearbeitet durch User
Wie praktisch. Das heißt es funktioniert bei allen Bitbreiten, nur aus unterschiedlichen Gründen. Kein Wunder, dass man auf Dauer paranoid wird.
:
Bearbeitet durch User
Walter T. schrieb: > Wie praktisch. Das heißt es funktioniert bei allen Bitbreiten, nur aus > unterschiedlichen Gründen. Kein Wunder, dass man auf Dauer paranoid > wird. Nein. Streng genommen ist es UB. Integer müssen nicht im 2-er Kompliment gespeichert werden...
Udo K. schrieb: > Walter T. schrieb: >> Wie praktisch. Das heißt es funktioniert bei allen Bitbreiten, nur aus >> unterschiedlichen Gründen. Kein Wunder, dass man auf Dauer paranoid >> wird. > > Nein. Streng genommen ist es UB. Integer müssen nicht im 2-er > Kompliment gespeichert werden... Seit C23 ist 2'er-Komplement verpflichtend.
Ich würde mit einer dieser beiden Lösungen arbeiten. Letztere ist vermutlich noch eindeutiger, während man bei der ersten beim Ändern der Datentypbreite die Zuweisung nicht ändern muss. Beim zweiten schreit in dem Fall aber hoffentlich irgendein Linter oder compiler ;) Peter D. schrieb: > uint64_t ullValue = -1; Simon schrieb: > UINT64_MAX
Udo K. schrieb: > Wilhelm M. schrieb: >> Seit C23 ist 2'er-Komplement verpflichtend. > > Das nützt dir nur heute nichts. Doch (bei gcc): -std=c2x Zitat cppreference: Prior to C23, the C Standard allowed any signed integer representation, and the minimum guaranteed range of N-bit signed integers was from (e.g. -127 to 127 for a signed 8-bit type), which corresponds to the limits of one's complement or sign-and-magnitude. However, all popular data models (including all of ILP32, LP32, LP64, LLP64) and almost all C compilers use two's complement representation (the only known exceptions are some compliers for UNISYS), and as of C23, it is the only representation allowed by the standard, with the guaranteed range from (e.g. -128 to 127 for a signed 8-bit type). Mit einem UB, was in der Tat heute(!) nicht auftritt, kann ich gut leben.
Wilhelm M. schrieb: > Udo K. schrieb: >> Nein. Streng genommen ist es UB. Integer müssen nicht im 2-er >> Kompliment gespeichert werden... > > Seit C23 ist 2'er-Komplement verpflichtend. Hallo, heißt das in Zukunft darf man auf signed Überläufen vertrauen wie man unsigned Überläufen vertrauen darf?
Veit D. schrieb: > Wilhelm M. schrieb: >> Udo K. schrieb: >>> Nein. Streng genommen ist es UB. Integer müssen nicht im 2-er >>> Kompliment gespeichert werden... >> >> Seit C23 ist 2'er-Komplement verpflichtend. > > Hallo, > > heißt das in Zukunft darf man auf signed Überläufen vertrauen wie man > unsigned Überläufen vertrauen darf? Nein, das bleibt UB.
Wilhelm M. schrieb: >> heißt das in Zukunft darf man auf signed Überläufen vertrauen wie man >> unsigned Überläufen vertrauen darf? > > Nein, das bleibt UB. Hast du da eine Referenz? Was wäre sonst der Sinn dahinter?
Wilhelm M. schrieb: >> Das nützt dir nur heute nichts. > > Doch (bei gcc): -std=c2x Die gcc Homepage meint dazu: A further version of the C standard, known as C2X, is under development; experimental and incomplete support for this is enabled with -std=c2x. Aber ich kenne keine aktuelle CPU, die nicht 2-er Kompliment hat, von daher ist die Diskussion sinnlos...
Udo K. schrieb: > Aber ich kenne keine aktuelle CPU, die nicht 2-er Kompliment hat, von > daher ist die Diskussion sinnlos... Sag ich doch!
Udo K. schrieb: > Wilhelm M. schrieb: >>> heißt das in Zukunft darf man auf signed Überläufen vertrauen wie man >>> unsigned Überläufen vertrauen darf? >> >> Nein, das bleibt UB. > > Hast du da eine Referenz? Was wäre sonst der Sinn dahinter? https://en.cppreference.com/w/c/language/operator_arithmetic#Overflows
Hallo, Schade das es nicht konsequent umgesetzt wird. Das würde viele Probleme beheben. Darf ich fragen was ein Trap ist? > ... representation (typically 2's complement), it may trap on some > platforms or due to compiler options (e.g. -ftrapv in GCC and Clang) ...
Veit D. schrieb: > Hallo, > > Schade das es nicht konsequent umgesetzt wird. Das würde viele Probleme > beheben. Darf ich fragen was ein Trap ist? >> ... representation (typically 2's complement), it may trap on some >> platforms or due to compiler options (e.g. -ftrapv in GCC and Clang) ... Ein trap ist ein Software-Interrupt, was das genau bedeutet, ist dann eben sehr plattformspezifisch. Auf x86/*nix wird dem Prozess ein SIGABRT gesendet.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.