amiga-news ENGLISH VERSION
.
Links| Forum| Kommentare| News melden
.
Chat| Umfragen| Newsticker| Archiv
.

amiga-news.de Forum > Programmierung > int test = 'TEST'; [ - Suche - Neue Beiträge - Registrieren - Login - ]

-1- [ - Beitrag schreiben - ]

16.05.2010, 22:27 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Hallo an alle C-Experten!

Ein Feature vermisse ich in C/C++ schmerzlich, oder ich weis einfach nicht wie es geht.

Wir alle kennen:

char x = 'A';

somit hätte x den Wert 65. Kann ich das auch mit 4 Bytes machen?
Das würde eine Menge Hickhack und ersparen.

Z.b. beim Lesen oder Schreiben von Dateien.

In Amiblitz mache ich z.B.

code:
file_WriteLong(fid,@"FORM");

oder

chunkId.l = file_ReadLong(fid);
Select chunkId
  Case @"ILBM" : ...
  Case @"CMAP" : ...
End Select


Ich möchte also eine 32 bit Konstante nicht decimal, nicht hexadecimal und auch nicht octal definieren, sondern auf 256 basis, also per ASCII Zeichen.




--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

16.05.2010, 22:45 Uhr

geit
Posts: 332
[Ex-Mitglied]
Ganz einfach:

# include <libraries/iffparse.h>

ULONG ID_ABCD = MAKE_ID('A','B','C','D');

oder in deinem Fall besser

#define ID_ABCD MAKE_ID('A','B','C','D')

Geit



[ Dieser Beitrag wurde von geit am 16.05.2010 um 22:52 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

17.05.2010, 11:29 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Gut, es ist kein direktes Amiga Programm, daher kann ich iffparse nicht einbinden, aber ich könnte das Macro "ausborgen". Obowhl ich eben die vielen Hochkommas vermeiden wollte, da bricht man sich beim tippen fast die Finger.

Bisher nutze ich das hier (für Big Endian):

code:
#define TagID(A) ((((int32)A[0])<<24)&0xFF000000) | ((((int32)A[1])<<16)&0x00FF0000) | ((((int32)A[2])<<8)&0x0000FF00) | ((((int32)A[3]))&0x000000FF)

switch(Id) {
  case TagID("TEST"): ...


aber das funktioniert nicht, da der Compiler es nicht schafft, daraus eine Konstante vorzuberechnen, damit ich das in einem switch/case nutzen kann.
Mal sehen ob das mit dem Macro aus iffparse geht.



--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ Dieser Beitrag wurde von Der_Wanderer am 17.05.2010 um 11:32 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

17.05.2010, 11:35 Uhr

Thore
Posts: 2266
Nutzer
MAKE_ID ist ein define auf folgendes:

#define MAKE_ID(a,b,c,d)
((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d))

Probier mal aus ob Dein Compiler hier eine Konstante berechnen kann. Sicher bin ich hier nicht, obgleich es durch die direkte Berechnung aber sein könnte.

[ Dieser Beitrag wurde von Thore am 17.05.2010 um 11:37 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

17.05.2010, 15:27 Uhr

geit
Posts: 332
[Ex-Mitglied]
Zitat:
Original von Der_Wanderer:
Gut, es ist kein direktes Amiga Programm, daher kann ich iffparse nicht einbinden, aber ich könnte das Macro "ausborgen". Obowhl ich eben die vielen Hochkommas vermeiden wollte, da bricht man sich beim tippen fast die Finger.


Hmm? Du definierst genau einmal dein ID_ABCD und benutzt genau diese Konstantennamen überall in deinem Programm und brauchst nicht nicht einen ' oder " zu benutzen.

Geit




[ Dieser Beitrag wurde von geit am 17.05.2010 um 15:34 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 16:22 Uhr

Thore
Posts: 2266
Nutzer
Noch nie Scheme oder Lisp programmiert? Da klammert man sich zu Tode :D Dagegen sind die 8 Hochkommas goldig :D

Ansonsten gilt das was geit sagt, ein define und Du bist die Tipperei los...

[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 16:26 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Nein, normalerweise nutze ich Amiblitz, da ist das ganz einfach.

Wie in meinem Titel

int test = 'TEST';

wäre ja nur konsequent gewesen. Oder statt

int test = 0xDEADBEEF
int test = 0aTEST

(a wie "ASCII").

Das mit den #defines ist schon eine Möglichkeit, miein Compiler frisst das auch als Konstante. Aber ist extra Aufwand. Kürzer geht's wohl nicht in C.


--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 17:55 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Wie in meinem Titel

int test = 'TEST';

wäre ja nur konsequent gewesen.

Na ja, es gibt C-Compiler, die das übersetzen. Aber das liegt außerhalb des Standards und dürfte aufgrund der Frage nach der zugehörigen Byte-Order auch als nette Fehlerquelle fungieren.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 17:58 Uhr

Der_Wanderer
Posts: 1229
Nutzer
@Holger

Es ist auch nicht gefählricher als beispielsweise Hex Zahlen:
int test = 0xDEADBEEF

Über die BO muss man sich im klaren sein, es ist eben nur eine andere Basis, 256 statt 16 oder 10, 8 oder 2.



--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 18:05 Uhr

geit
Posts: 332
[Ex-Mitglied]
@Der_Wanderer:

Ähm, eine der IMHO ungeschriebenen Regel in C ist, das man keine Zahlen/Konstanten im Quellkode verwendet, sondern diese in sinnvollen defines auslagert/vorlagert.

Dadurch hat man dann auch später keine Probleme, wenn man mal eine Puffergröße ändern oder wie in deinem Fall die Lade/Speicher Routine für was anderes verwenden will. Man ändert einfach nur die Defines und an allen 20 Stellen ändert sich der Wert automatisch mit und der Programmkode funktioniert immer noch, weil man nicht einen vergessen hat.

Wenn man das nicht macht, dann bekommt man schnell mal einen Pufferüberlauf, oder andere Fehlfunktionen und sucht sich nen Wolf. Es erhöht auch die Lesbarkeit den Quellkodes. Eine 7 ist halt nicht so aussagekräftig wie ein MAX_DEVICE_UNIT.

Geit


[ Dieser Beitrag wurde von geit am 18.05.2010 um 18:18 Uhr geändert. ]

[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 18:42 Uhr

Der_Wanderer
Posts: 1229
Nutzer
@geit
Solche grundlegenden Programmiertechniken sind mir schon klar ;-)

Bei einer lade Routine spricht aber eigentlich nichts (nicht viel) dagegen, mal eben sowas wie


if (chunkId == 'ILBM') ...

zu machen. Das ist genauso gut lesebar wie

#define ID_ILBM <blablablabla>

if (chunkId == ID_ILBM) ...

zumal man direkt sieht, dass nach "ILBM" gesucht wird. Hier haben wir den umgekehrten fall, wenn ich mich bei dem Define vertippe, dann muss ich mir den Wolf suchen, weil man bei ID_ILBM davon ausgeht dass es stimmt.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 18:44 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
@Holger

Es ist auch nicht gefählricher als beispielsweise Hex Zahlen:
int test = 0xDEADBEEF

Für Zeichenketten gelten allerdings andere Regeln als für Zahlenkonstanten. Somit wirft das schon die Frage auf, ob 'ABCD' nun eine Zahl oder eine Zeichenkette ist.

Die Lösung mit einem Makro à la makeid erlaubt es Dir, selbst zu entscheiden, wie es gemeint ist. Deshalb ist es dann auch nicht die Schuld von C, wenn Du IDs wie IFF-Tags als int liest und auf LE Systemen auf die Nase fliegst...
Zitat:
Original von geit:
Eine 7 ist halt nicht so aussagekräftig wie ein MAX_DEVICE_UNIT.

Das mag bei dem Beispiel stimmen, aber ID_ABCD ist nicht wirklich aussagekräftiger als 'ABCD'. Und die Annahme, man würde eine solche Konstante im Nachhinein ändern, halte ich in diesem Fall für äußerst gewagt. Denn ob ein für ein #define ID_ABCD makeid('X', 'Y', 'Z', 'Q') wirklich noch gilt, dass der Code wartbarer als die Verwendung der direkten Konstante ist, glaube ich eher nicht.

Im übrigen habe ich wirklich schon mal Code gesehen, in dem Konstanten namens one=1 zero=0 minus_one=-1 definiert wurden. Da sieht man, was dabei rauskommt, wenn Programmierer bestimmte ungeschriebene Gesetze anwenden, ohne über deren Sinn nachzudenken. Allerdings war das kein C, sondern Fortran-Code...

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 18:50 Uhr

Der_Wanderer
Posts: 1229
Nutzer
Ziffern als Macros zu machen ist schwachsinn, denn z.b. das ASCII Zeichen "1" bezeichnet diese Ziffer bereits perfekt, kann man bereits als #define 1 1 sehen, wenn man das so will.
Ein #define mit namen macht erst Sinn, wenn es nicht um die Zahl geht, sondern wenn es eine Logische Bedeutung hat, wie z.B. MAX_DEVICE_IDS oder sowas.
Aber hier in dem Fall ist mit 'ILBM' tatsächlich, wie bei der 1, genau dieser Wert gemeint, und kein anderer. (und auf keinen Fall ein anderer!!! das wäre fatal).

Wegen der BO, das darf man natürlich nicht aus der Datei als char Array lesen, wenn man das später als Integer haben will. Aber das ist eine andere Geschichte. In dem Fall ist ILBM einfach die 32 Bit Zahl die sich daraus ergibt.

--
HD-Rec, Sweeper, Samplemanager, ArTKanoid, Monkeyscript, Toadies, AsteroidsTR, TuiTED, PosTED, TKPlayer, AudioConverter, ScreenCam, PerlinFX, MapEdit, AB3 Includes und viele mehr...
Homepage: http://www.hd-rec.de


[ - Antworten - Zitieren - Direktlink - ]

18.05.2010, 19:33 Uhr

Holger
Posts: 8116
Nutzer
Zitat:
Original von Der_Wanderer:
Wegen der BO, das darf man natürlich nicht aus der Datei als char Array lesen, wenn man das später als Integer haben will. Aber das ist eine andere Geschichte. In dem Fall ist ILBM einfach die 32 Bit Zahl die sich daraus ergibt.

Eben nicht.
Der ILBM-Marker ist die Zeichenfolge 'I' 'L' 'B' 'M', und zwar genau in dieser Reihenfolge.
Wenn Du den Marker als Integer-Wert liest, wird die Byte-Order des Systems angenommen, das heißt bei LE-Systemen ist M das höchste byte des resultierenden Integer-Werts, während das Macro makeid, bzw. der Ausdruck (('I'<<24) | ('L'<<16) | ('B'<<8) | 'M') ausdrücklich das 'M' als niedrigstes byte deklariert.

Ein Vergleich als (single-byte-) Zeichenkette würde dagegen immer davon ausgehen, dass die bytes in der Reihenfolge wie im Code aufgeführt gespeichert werden, egal welche Endianess das System hat, und somit das Richtige tun.

Allerdings sehen typische Implementierungen so aus, dass sie ein Makro wie hier beschrieben zusammen mit einem Makro zum Lesen eines Big-Endian Integer Wertes kombinieren, somit zwar das Richtige tun, aber auf LE-Systemen überflüssige byte-swap Befehle generieren.

--
Good coders do not comment. What was hard to write should be hard to read too.

[ - Antworten - Zitieren - Direktlink - ]


-1- [ - Beitrag schreiben - ]


amiga-news.de Forum > Programmierung > int test = 'TEST'; [ - Suche - Neue Beiträge - Registrieren - Login - ]


.
Impressum | Datenschutzerklärung | Netiquette | Werbung | Kontakt
Copyright © 1998-2024 by amiga-news.de - alle Rechte vorbehalten.
.