Forum>Entwickler>Ist ~0 == -1 immer wahr?

Ist ~0 == -1 immer wahr?

andreas_g
andreas_g14.03.2115:03
Eine Frage an alle Experten hier:

Ist die Aussage ~0 == -1 auf allen Plattformen zutreffend (Programmiersprache C) oder gibt es Plattformen, die negative Zahlen anders definieren?

Falls es hier (exotische) Ausnahmen gibt: Wie könnte ich das zur "Compile-Time" verlässlich prüfen lassen?
0

Kommentare

Perdiste puesto primero17.04.2120:08
In C ist das auf allen Plattformen so, allerdings solltest Du sicherheitshalber auf signed casten.

Aber Achtung: andere Programmiersprachen sind teils deutlich restriktiver, da stimmt das nicht zwingend.
0
Marcel Bresink18.04.2110:10
andreas_g
Ist die Aussage ~0 == -1 auf allen Plattformen zutreffend

Nein, das gilt nur für Prozessoren, bei denen für vorzeichenbehaftete Ganzzahlarithmetik das Zweierkomplement-Verfahren verwendet wird.
andreas_g
Programmiersprache C

Die Normung der Programmiersprache C legt ausdrücklich fest, dass dieses Verhalten implementationsabhängig, also gerade nicht genormt ist. Das heißt zur Compile-Zeit ist es unmöglich, das in der Programmiersprache C normgerecht zu prüfen, falls man im Vorhinein nichts über den Prozessor weiß.
+5
andreas_g
andreas_g18.04.2112:37
Marcel Bresink
andreas_g
Programmiersprache C

Die Normung der Programmiersprache C legt ausdrücklich fest, dass dieses Verhalten implementationsabhängig, also gerade nicht genormt ist. Das heißt zur Compile-Zeit ist es unmöglich, das in der Programmiersprache C normgerecht zu prüfen, falls man im Vorhinein nichts über den Prozessor weiß.

Danke! Verstehe ich das also richtig, dass theoretisch auf dem Rechner, mit dem kompiliert wird, das Zweierkomplement-Verfahren angewendet werden könnte, während auf dem ausführenden Rechner ein anderes Verfahren zum Einsatz kommt und man das deshalb zur Laufzeit prüfen müsste?
+1
tmlen27.04.2114:31
Implementationsabhängig (implementation-defined behavior) bedeutet dass das Verhalten vom Compiler abhängt, und in diesem Fall auch von der CPU Architektur, für die kompilliert wird. (Im allgemeinen bedeutet es dass die "abstract machine" welche den C-code interpretiert, und nicht die C-Norm, das Verhalten definiert. Im Normalfall mit C ist die "abstract machine" der Compiler, welcher das C-Programm in Maschinencode übersetzt.)

Es kann zur Kompile-Zeit geprüft werden mithilfe des Preprozessors:

#if ~0 == -1
#define TWOS_COMPLEMENT
#endif

int main() {
    #ifdef TWOS_COMPLEMENT
    printf("two's complement\n");
    #else
    printf("not two's complement\n");
    #endif
}

Ein Programm das für eine Rechner-Architektur mit Zweierkomplement kompilliert wurde, kann nur auf solchen Rechnern laufen, es muss also nicht zur Laufzeit überprüft werden. ~0 == -1 ist eine compile-time constant.

Selbst wenn für eine andere Architektur kompilliert wird als die des Compilers (cross-compillation), ergibt ~0 == -1 zur Kompillierzeit das Ergebiss, das es auf der Ziel-Architektur haben wird.

In der Praxis verwenden (fast) alle Rechner das Zweierkomplement-System.
+2
andreas_g
andreas_g27.04.2115:03
Danke für die Erklärung! Das hilft mir weiter! Mittlerweile hat sich noch eine weitere Frage ergeben:

uint32_t a, b;
#define c 0xFFFFFF00
a = 0x1FF;
b = 0x100;

if (a == b | ~c) { ... }

Wird die Bedingung im if-Statement immer wahr sein, oder muss ich hier die Variable c in uint32_t casten für den Fall, dass auf einem System der Typ int beispielsweise 64 bit lang ist?
0
pstoehr27.04.2117:01
Nur mal so aus reiner Neugierde, was programmierst du denn konkret dass du so etwas auf "Bit-Ebene austrägst"?
0
andreas_g
andreas_g27.04.2118:24
Einen Emulator: Previous
+2
frankh27.04.2118:49
Ganz allgemein würde ich soviel wie möglich explizit hinschreiben, also hier casten. Kommt natürlich drauf an, wie sehr man bits sparen muss.
Moderne Compiler sind aber Wunderwerke im weg-optimieren. Da muss man als Programmierer nicht mehr soviel vordenken wie früher.

In diesem Sinne würde ich auch mit Klammern nicht geizen, um mich nicht auf die Priorität bei der Auswertung von Ausdrücken zu verlassen.
Das kostet nichts und man weiss auch morgen noch was man gemeint hat
if (a == (b | ~c)) ...
andreas_g
Danke für die Erklärung! Das hilft mir weiter! Mittlerweile hat sich noch eine weitere Frage ergeben:

uint32_t a, b;
#define c 0xFFFFFF00
a = 0x1FF;
b = 0x100;

if (a == b | ~c) { ... }

Wird die Bedingung im if-Statement immer wahr sein, oder muss ich hier die Variable c in uint32_t casten für den Fall, dass auf einem System der Typ int beispielsweise 64 bit lang ist?
0
gfhfkgfhfk29.04.2116:11
andreas_g
Wird die Bedingung im if-Statement immer wahr sein, oder muss ich hier die Variable c in uint32_t casten für den Fall, dass auf einem System der Typ int beispielsweise 64 bit lang ist?
c ist keine Variable, sondern ein Makro. D.h. der Präprozessor ersetzt es immer wenn er c sieht mit dem Literal 0xFFFFFF00. Literale ohne Typangabe werden in C üblicherweise als int interpretiert. An dieser Stelle wäre also 0xFFFFFF00u sinnvoller.
0
ssb
ssb30.04.2101:37
Das einzige was in C definiert ist - wird meist in den std Headern gemacht.
#define FALSE 0
#define TRUE !FALSE

und da geht es schon los. !0 ist nicht zwingend 1, manchmal auch -1, je nachdem. Daher wird TRUE eben als nicht FALSE definiert. Je nachdem wie der Compiler oder die Architektur das eben interpretiert.
Clang/LLVM macht das zum Beispiel anders als msvc, gcc oder Borland.
Da sollte man immer ganz genau auf Warnings achten oder besser -Wall benutzen.
0
ssb
ssb30.04.2101:39
was wollt ihr denn emulieren?
Ich dachte mal daran mein altes ECB-85 Board zu emulieren…
andreas_g
Einen Emulator: Previous
0
LoCal
LoCal30.04.2108:15
ssb
was wollt ihr denn emulieren?
Ich dachte mal daran mein altes ECB-85 Board zu emulieren…
andreas_g
Einen Emulator: Previous

Previous emuliert NextStation (Color/Turbo) und NextCube inkl. DimensionBoards.
„Ich hab zwar keine Lösung, doch ich bewundere dein Problem“
0
ssb
ssb30.04.2112:02
LoCal
ssb
was wollt ihr denn emulieren?
Ich dachte mal daran mein altes ECB-85 Board zu emulieren…
andreas_g
Einen Emulator: Previous

Previous emuliert NextStation (Color/Turbo) und NextCube inkl. DimensionBoards.
Ambitioniert.
Es gibt ja schon Emulatoren für 68k-CPUs. Transcoding wäre da aber interessanter - also quasi Rosetta für 86k CPUs. Ich hatte mal an dem Projekt "libcpu" mitgearbeitet (habe einen PPC Disassembler beigesteuert) - leider ist das Projekt praktisch tot - aber das wäre ein guter Ansatz - aber das können wir gerne auch per PM vertiefen.
0
LoCal
LoCal30.04.2112:14
ssb
LoCal
ssb
was wollt ihr denn emulieren?
Ich dachte mal daran mein altes ECB-85 Board zu emulieren…
andreas_g
Einen Emulator: Previous

Previous emuliert NextStation (Color/Turbo) und NextCube inkl. DimensionBoards.
Ambitioniert.
Es gibt ja schon Emulatoren für 68k-CPUs. Transcoding wäre da aber interessanter - also quasi Rosetta für 86k CPUs. Ich hatte mal an dem Projekt "libcpu" mitgearbeitet (habe einen PPC Disassembler beigesteuert) - leider ist das Projekt praktisch tot - aber das wäre ein guter Ansatz - aber das können wir gerne auch per PM vertiefen.

Previous läuft doch schon und ziemlich gut sogar. Mittlerweile ist auf previous bei Version 2.3
„Ich hab zwar keine Lösung, doch ich bewundere dein Problem“
0

Kommentieren

Sie müssen sich einloggen, um sich an einer Diskussion beteiligen zu können.