crc über struct c#

Gast #1945344
Lesenswert?

Hallo Freunde,
ich habe ein Problem bei dem ich als absoluter Anfänger nicht mehr 
weiter komme.
Ich habe folgende Structur und muß eine CRC Prüfsumme erzeugen.
Die Methode zur Erstellung der CRC möchte ein byte array haben.
Zu meinem Problem wie kann ich aus der Structur ein byte Array erzeugen 
und wie aus einem Array eine Structur?
ich hoffe ich konnte meine Frage einiger Massen deutlich stellen.
1
public struct Protocol
2
        {
3
            public byte adress;
4
            public byte  command;
5
            public byte len;
6
            public Int16 [] recivebuffer;
7
            public int Rtimeout;
8
            public Int16 rec_CRC;
9
        };

Gruß

Pingo
Gast #1945376
Lesenswert?

C# ist eine Hochsprache und da kann man sich nicht darauf verlassen das 
die Bytes in einer Struktur so hintereinanderliegen wie man das 
maschinennah gerne hätte. Deshalb ist das hier etwas 'umständlicher':
- einen MemoryStream ms erzeugen
- einen BinaryWriter bw(ms) erzeugen
- die Elemente nacheinander mit bw.Write(data) in den Stream schreiben
- aus dem Stream ein Array erzeugen mit byte[] ba = ms.ToArray();

Alternativ kann man eine Struktur mit Marshalling Attributen versehen 
und mit Pointern hantieren, aber das ist weniger im Sinne von .Net.
Gast #1945383
Lesenswert?

> - die Elemente nacheinander mit bw.Write(data) in den Stream schreiben

Das wird so (noch) nix, weil die Endianness noch nicht erklärt ist 
(betrifft hier int und int16). Abgesehen davon gehts auch ohne Umweg: 
Ein byte[] hinreichender Größe erzeugen, die Daten (unter Beachtung der 
Endianness) byteweise reinkopieren, fertig.

HTH und HF
Gast #1945409
Lesenswert?

1
struct Protocol x = ..;
2
int länge = sizeof(struct Protocol) -sizeof(int16*) +x.len;
3
byte[] b = new byte[länge];
4
int i = 0;
5
b[i] = x.adress; i++;
6
b[i] = x.command; i++;
7
b[i] = x.len; i++;
8

9
for (int j = 0; j < x.len; j++) {
10
   b[i] =  x.recivebuffer[j]       & 0xFF; i++;
11
   b[i] = (x.recivebuffer[j] >> 8) & 0xFF; i++;
12
}
13

14
b[i] =  x.Rtimeout       & 0xFF; i++;
15
b[i] = (x.Rtimeout >> 8) & 0xFF); i++;

Der Süntacktische Schugar verbleibt beim geneigten Hausaufgabenmacher 
;-) Und ich kann hier gerade weder Syntax noch Semantik überprüfen weil 
ich gerade keinen Siehäsch-Compiler zur Hand hab - die Grundidee sollte 
aber rüberkommen.

Ob Big- oder Little-Endian (hier: letzteres) steht in der Protokolldoku. 
Ob die crc32 mit dazgehört, ggf. mit Nullen aufgefüllt, ob die Eingabe 
sonstwie aufgefüllt werden muss oder sonst noch was fehlt, das steht in 
der Doku :-)

HTH und HF
Gast #1945413
Lesenswert?

Ich stelle grad fest ein int ist 4 Bytes groß, also musses heissen..
1
[..]
2
int länge = sizeof(struct Protocol) -sizeof(int16*) +x.len *4;
3
[..]
4
for (int j = 0; j < x.len; j++) {
5
   b[i] =  x.recivebuffer[j]        & 0xFF; i++;
6
   b[i] = (x.recivebuffer[j] >>  8) & 0xFF; i++;
7
   b[i] = (x.recivebuffer[j] >> 16) & 0xFF; i++;
8
   b[i] = (x.recivebuffer[j] >> 24) & 0xFF; i++;
9
}
</ingrid>
Gast #1945418
Lesenswert?

Das die BinaryWriter Lösung nur Little-Endian kann ist richtig, sieht 
aber eleganter aus, vor allem wenn noch 32Bit Integer, Floating Point 
oder Textfelder in das Protokoll reinsollen. Ist dann vielleicht 
geschmacksache und glücksache das die Formate passen.
Gast #1945444
Lesenswert?

> und wenn der receiveBuffer[] eine unbestimmte Länge hat wird
> sizeof(struct Protocol) nichts brauchbares liefern.

Der soll genau die Größe der Stuktur liefern (inklusive des Zeigers auf 
das Array, der danach wieder abgezogen wird - oder ist das in Siehäsch 
anders definiert?). Die Größe des Datenpakets interpretiere ich jetzt 
einfach mal als das Feld len. Damit weiss man dann genau wie groß das 
Datenpaket wirklich ist (in Bytes).

Ob Big oder Litte, das steht wie gesagt in der Protokollspeck. Wie 
Floats anzugeben sind ebenso. Und der ganze Rest natürlich auch :-) In 
der Regel ist es zweckmäßig ebendieses Speck zu lesen ;-)

HTH und HF

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