int Variable:4 ???
-
Grüsse zusammen,
Ich glaube es ist C, bin mir aber irgendwie gar nicht sicher. Hab es noch nie gesehen und verstehe dadurch auch nicht was es bedeutet:
typedef struct { unsigned int nLength:4; // anderen Quatsch. } EinName;
Was bedeutet dieses Doppelpunkt 4? Was wird dadurch erreicht? Was muss ich mir darunter vorstellen?
Danke für die Hilfe.
Grüssli
-
Es handelt sich um ein BitField der Länge 4
unsigned int nLength:4
kann also Werte zwischen 0 und 2^4-1=15 aufnehmen.
Für solche Fragen schau dir am besten die Language Specifikation
an; einen Link darauf wird bestimmt in der hiesigen FAQ zu finden sein.
-
#include <iostream> using namespace std; typedef struct { unsigned int red:8; unsigned int yellow:8; unsigned int blue:8; unsigned int:8; } color; int main() { color test; test.blue = 0x55; test.yellow = 0xFF; test.red = 0xA0; cout << sizeof(test) << endl; cout << "red:\t " << test.red << endl; cout << "yellow:\t " << test.yellow << endl; cout << "blue:\t " << test.blue << endl; return 0; }
Wäre ein solches vorgehen im Umgang mit 24bit Werten zu empfehlen?
Rein vom Code her wäre es meiner Meinung nach übersichlicher und klarer
als irgendwelche Bitmanipulationen alla "(char)((color<<8)>>24)".Doch wie sieht es perfomancemässig aus? Wird dieser Code einfach nur
mithilfe von Bitmanipulationen ausführbar gemacht. Oder wie funktioniert es im
Endeffekt das ich auf 8Bit einzeln zugreifen kann?//EDIT: Sorry merke grad das ich hier ja im Ansi-C Forum poste.
Ich denke für die Frage macht es aber keinen unterschied in
was der beispiel code geschrieben ist.
-
Storm.Xapek.de schrieb:
Wäre ein solches vorgehen im Umgang mit 24bit Werten zu empfehlen?
würde ich nicht zu raten. so'n compiler ist immer bestrebt es sich einfach und den code schnell zu machen ohne gegen die ansi/iso specs zu verstossen. d.h. er kann da löcher reinhauen wenn's ihm passt. manchen kann man's zwar abgewöhnen mit __ATTRIBUTE_PACKED__ oder #pragma pack(1) aber verlassen würd' ich mich nicht drauf...
-
Hmmm in den FAQs hat es glaub ich keine "Language Specification". Zumindest habe ich nichts in der C und C++ FAQ gefunden. Aber auch nicht so wichtig, verstanden habe ich es ja. Allerdings begreif ich nun einen Quellcode nicht mehr ^^
Ich schreibe mal ein wenig Code hin und ihr erklärt mir, wie dies möglich ist! BITTE!
typedef struct { unsigned char VIHL; unsigned char TOS; short TotLen; // Länge dieser Struktur (sizeof(IPHDR)). short ID; short FlagOff; unsigned char TTL; unsigned char Protocol; unsigned short Checksum; unsigned long iaSrc; unsigned long iaDst; } IPHDR;
Wenn es jemand erkennt, ja, das sollte eigentlich einen standard IP ICMP Header sein.
Wie können nun folgende zwei Codeausschnitte das gleiche tun!
char szBuffer[1024]; // szBuffer hat ganz am Anfang eine IPHDR Struktur drin. Der Rest sind irgendwelche Daten. // Codeausschnitt 1: typedef struct { unsigned int h_len:4; // Länge des Headers char szAdditionalData[23]; // Enthält uninteressante Daten. } ip_header_t; // ... In einer Funktion ... ip_header_t* pIPHeader = (ip_header_t*)szBuffer; char* pByte = (char*)(szBuffer + pIPHeader->h_len * 4); /* Laut Autor soll nun pByte die Adresse auf das erste Byte enthalten nach der IPHDR Struktur in szBuffer. Also pByte beinhaltet die Adresse des ersten Bytes der restlichen Daten. */ // Codeauschnitt 2 typedef struct { IPHDR hdr; char cFiller[1024]; } REPLY; // ... In einer Funktion ... REPLY* pReply = (REPLY*)szBuffer; /* Laut Autor ist nun REPLY::cFiller die Adresse auf das erste Byte der restlichen Daten. Finde ich persönlich auch logisch. */
Ich hoffe, ihr könnt mir helfen. Danke jedenfalls schonmal für die Hilfe.
Grüssli
-
zu 1:
der coder verlässt sich darauf, dass sein compiler für 'h_hlen' 1 byte benutzt (die oberen 4 bits) dann 4 bits auslässt und bis zum beginn von 'szAdditonalData' keine löcher einbaut d.h. sizeof(ip_header_t) muss 24 sein sonst geht's nicht.
mit der codezeile:
'char* pByte = (char*)(szBuffer + pIPHeader->h_len * 4);'
möchte er einen pointer auf die daten hinter den ip header bekommen (normalerweise ist dort der header der nächsten protokollschicht).
mit dem '+ pIPHeader->h_len * 4' überspringt er den variablen anteil des ip headers (die options). 'h_len' ist die anzahl der 32bit-werte aus denen der ip-header einschliesslich aller options besteht. ein ip-header ohne options ist 20 bytes lang.zu 2:
der coder benutzt seine IPHDR struktur (er vertraut seinemm compiler und nimmt an, dass diese 20 bytes gross ist) und hängt noch 1024 bytes dran. dieses konstrukt geht davon aus, dass der ip header keine options hat (oder er möchte mit dem pointer auf die options zugreifen).btw: alles in allem sind diese codes ziemliches flickwerk. stammen sicher von irgend so'nem linux-kid
-
Danke, trotzdem habe ich noch eine Frage zum Teil 1. Aber zuerst eine Aussage zu deinem btw. Code Ausschnitt 1 stammt von www.c-worker.ch. Code Auschnitt 2 von www.codeproject.com WinPing.
Profil des Autors
Ein Windows Senior Software Engineer. Ok da trifft wohl geflicke durchaus zu.
Bei c-worker weiss ich es nicht.Nun zu der Frage. Ich versteh es nämlich immer noch nicht, wie der es mit dem ganzen macht. Denn wenn schon würde ich es so "flicken". (Ich bin ja auch ein Neuling, darf also das machen :p).
typedef struct { unsigned char cFirstData[2]; // Daten vor der Länge unsigned short nLength; // Länge des IPHeaders } ip_header_t; ip_header_t* pIPHeader = (ip_header_t*)szBuffer; char* pByte = (char*)(szBuffer + pIPHeader->nLength); // Man könnte auch gleich, ohne irgendwelche structs, folgendes machen: unsigned short nLength = *(unsigned short*)(szBuffer + 2); char* pByte = (char*)(szBuffer + nLength);
So hole ich direkt aus der Struktur IPHDR die Länge von der Struktur, nämlich TotLen. Und rechne dann diese Anzahl Bytes dem Zeiger dazu, wodurch dieser mir dann auf das richtige Byte zeigen sollte.
Der Code von C-Worker macht dies doch aber nicht. Der greift auf die ersten 4 Bits der Struktur IPHDR zu und rechnet dann den Wert, welcher dort drin ist, mal 4. Die ersten 4 Bits definieren aber die Version des IPHDR, bzw. sind Teil des VIHL Bytes. Das hat doch nix mit der Länge des Headers zu tun, wodurch er doch nicht die richtige Anzahl Bytes dazurechnen kann. Oder bin ich irgendwie völlig auf dem Holzweg?
Grüssli
-
du greifst auf das feld 'total length' zu. das ist die gesamtlänge das pakets einschliesslich ip-header selber und was da noch alles drin stecken mag. z.b. ein tcp header und payload (nutzdaten). dieser 'windows senior software frickler' greift auf das feld 'internet header length' zu. dieses feld gibt die grösse des ip headers + options in 32 bit words an. ein ip header ist mindestens 20 bytes lang also hat dieses feld mindestens den wert '5'. er weiss, das sein compiler für einen einzelnen bitfieldmember der länge 4 die *oberen* 4 bits benutzt. ein anderer compiler (z.b. einer für eine big-endian maschine) hätte die untreren 4 bits gewählt und sein code wäre da nicht lauffähig.
edit:
guckst du: http://www.ietf.org/rfc/rfc791.txt
kapitel 3 absatz 1ach, noch was,
dein code:unsigned short nLength = *(unsigned short*)(szBuffer + 2);
klappt auch nicht immer weil multibyte werte in ip headern in 'network byte order' sind. wenn du das auf 'ner x86 gurke machst (die arbeiten mit der 'brain damaged byte order') musst du beide bytes vertauschen z.b. mit der funktion 'htons'
-
Dravere schrieb:
...
typedef struct { unsigned int nLength:4; // anderen Quatsch. } EinName;
...
Gibt's das eigentlich auch in ANSI C oder ist das eine C++-Spezialität ?
Gruß,
Simon2.
-
Das gibt's auch in ANSI C.
-
TactX schrieb:
Das gibt's auch in ANSI C.
Danke !
Gruß,
Simon2.