Forum: PC-Programmierung Funktion mit Arrays und Hex-Zahlen


von Joey T. (j0sef)


Lesenswert?

Hallo zusammen,

ich benötige mal wieder Hilfe aus der µC-Gemeinde.

Folgendes Problem: Ich habe 4 Variablen Byte1 bis Byte4 vom Typ Int. 
Diese 4 Variablen beinhalten Hex-Zahlen, bspw. A0. Außerdem habe ich 
eine Funktion in der ich diese 4 Bytes mit einander verketten möchte zu 
einer Variablen X, damit ich diese Variable X als Rückgabewert wieder 
herausgeben kann aus der Funktion.

Noch zur Info: Ich arbeite mit dem TASKING VX-toolset V3.1

Alle Bibliotheken und Headerdateien sind natürlich vorhanden die ich 
dafür brauche nur bei mir will der einfach nicht X wiedergeben, da ich 
es bisher mit einem Array versucht habe.

Außerdem wäre es nicht schlecht, wenn man mit der zurück gegebenen 
Variablen X auch die einzelnen Bytes wieder extrahieren kann zur 
eventuellen Weiterverarbeitung oder Auswertung.


Danke schon mal im Voraus

Gruß,

Josef

von Peter II (Gast)


Lesenswert?

Joey T. schrieb:
> Ich habe 4 Variablen Byte1 bis Byte4 vom Typ Int.
> Diese 4 Variablen beinhalten Hex-Zahlen, bspw. A0

nein machen sie nicht, ein INT wert kann keine Hexzahlen enthalten. HEX 
ist eine Darstellungsform. Sie kann maximal in einem String stehen.

Also bitte noch mal von vorne: Was willst du haben, möglichst mit 
Beispiel?

von Decius (Gast)


Lesenswert?

Ok, eine dezimale zahl kann als binäre zahl dargestellt werden. 
unterteile ich diese binäre zahl in ihre nibbel, kann man direkt 
nibbelweise die hexadeziamle darstellung ablesen. ob hexadezimal oder 
binär sind also nur unterschiedliche betrachtungsweisen des selben 
bitmusters.

von Udo S. (urschmitt)


Lesenswert?

Joey T. schrieb:
> Ich habe 4 Variablen Byte1 bis Byte4 vom Typ Int.
Sind das jetzt Bytes oder Int. Wenn Int welcher Wertebereich? Mit oder 
ohne Vorzeichen?
Du musst präzise sein.

von Joey T. (j0sef)


Lesenswert?

Ok, mein Fehler, nochmal von vorn:

Ich habe 4 Variablen Byte1 bis Byte4 vom Typ char und beinhalten jeweils 
eine Zahl die nicht größer als 1 Byte ist (max. Wertebereich von char). 
Diese sind nicht mit einem Vorzeichen behaftet. Diese 4 Werte erhalte 
ich aus einer Unterfunktion, die ich 4 mal aufgerufen haben und den 
Byte1 bis Byte4 jeweils zugewiesen habe. Jetzt möchte ich eigentlich nur 
diese 4 Werte mit einander verketten in einer Variablen und diese als 
Rückgabewert aus der Funktion wiedergeben.

Mit diesem Rückgabewert muss aber noch weitergearbeitet werden, wobei 
die Werte Byte1 und Byte2 zusammen gehören und Byte3 mit Byte4.
Die Anordnung wäre diese: 0bXXXXXXXX XXXXXXXX => 0bByte2 Byte1. Könnte 
man dafür einfach das Byte2 um 8 Bits nach links verschieben und dann 
mit Byte1 addieren?

Ein Beispiel:
Rückgabewert Hauptfunktion(a,b)
{
Byte1 = Unterfunktion(x);
Byte2 = Unterfunktion(y);
Byte3 = Unterfunktion(z);
Byte4 = Unterfunktion(a);

/*
Variable_K soll nun diese 4 Werte mit einander verketten und als 
Rückgabewert aus der eigentlichen Fuunktion kommen.
*/
return Variable_K;
}

Nun möchte ich mit diesem Wert weiter arbeiten, bspw. möchte ich das 
kombinierte Byte1 und Byte2 mit einem Wert vergleichen. Gleiches gilt 
für das kombinierte Byte3 und Byte4.

Danke im Voraus

Gruß,

Josef

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Zwei 8-Bit-Werte lassen sich selbstverständlich zu einem 16-Bit-Wert 
zusammenfassen:

uint8_t a = 0x12;
uint8_t b = 0x23;

uint16_t x;

x = (a << 8) + b;


Allerdings: Wenn Deine Funktion Deine vier Werte zu zweien 
zusammenfasst, aber nur einen davon zurückgibt, kannst Du außerhalb der 
Funktion nichts mit dem anderen Wert anstellen, der ist dann weg.

von Joey T. (j0sef)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Allerdings: Wenn Deine Funktion Deine vier Werte zu zweien
>
> zusammenfasst, aber nur einen davon zurückgibt, kannst Du außerhalb der
>
> Funktion nichts mit dem anderen Wert anstellen, der ist dann weg.

Dem bin ich mir auch bewusst. Was ich sagen wollte ist, dass ich schon 
alle 4 Werte aus der Funktion erhalten möchte. Ich habe das mit dem 
kombinieren der Bytes gesagt, damit es klar ist wie ich weiter arbeiten 
möchte mit den Werten. Ich könnte mir das so vorstellen:

long int Variable_K = (Byte4<<24)+(Byte3<<16)+(Byte2<<8)+Byte1;

Diese Variable_K könnte ich dann doch als Rückgabewert nutzen, wenn 
natürlich meine Funktion auch mit dem gleichen Rückgabetyp definiert 
wird!?

Frage ist nun, wenn ich bspw. die kombinierten Bytes4 und 3 mit dem Wert 
0xA1B2 vergleichen möchte?

Mir würde jetzt nur spontan einfallen, so wie ich es erstellt habe, so 
mache ich es auch wieder rückwärts. sprich Variable_K >> 16;

von Volkmar D. (volkmar)


Lesenswert?

Wenn Du sagst, das die einzelnen chars zusammengehören, dann mache es 
doch mit einer Union:
1
typedef union
2
{
3
    uint32_t as_uint32;
4
    int32_t  as_int32;
5
    uint16_t as_uint16[2];       // avr uses little endian - LSB is uint16[0]
6
    int16_t  as_int16[2];
7
    uint8_t  as_uint8[4];       // avr uses little endian - LSB is uint8[0]
8
    int8_t   as_int8[4];
9
    struct                      // if code runs on other endianess - change here
10
      {
11
        uint8_t  lolo8;
12
        uint8_t  lohi8;
13
        uint8_t  hilo8;
14
        uint8_t  hihi8;
15
      };
16
} t_data32;
17
18
t_data32 foo;

Dann kannst Du auf die 4 Werte wie folgt zugreifen:
1
// Byteweise
2
bar = foo.as_int8[0];
3
bar = foo.as_int8[1];
4
bar = foo.as_int8[2];
5
bar = foo.as_int8[3];
6
7
// Als uint16_t
8
bar = foo.as_uint16[0];
9
bar = foo.as_uint16[1];
10
11
// usw

von Thomas E. (thomase)


Lesenswert?

So geht's auch:

char nByte[4] = {0x11, 0x22, 0x33, 0x44};
int* nX = (int*) nByte;
short* nSlow = (short*) nByte;
short* nShigh = (short*) (nByte + 2);

void Funktion(<Para>)
{
   nByte[0] = Unterfunktion(x);
   nByte[1] = Unterfunktion(y);
   nByte[2] = Unterfunktion(z);
   nByte[3] = Unterfunktion(a);
}

Joey T. schrieb:
> Frage ist nun, wenn ich bspw. die kombinierten Bytes4 und 3 mit dem Wert
> 0xA1B2 vergleichen möchte?

if (*nShigh == 0xA1B2)
{

}

mfg.

von Joey T. (j0sef)


Lesenswert?

Habe es jetzt erst mal so gelöst, wie ich es in meinem letzten Post 
gesagt habe.

long int Funktion(q,w)
{
char Byte1 bis 4;
long int Variable_K;

Byte1 = Unterfunktion(x);
Byte2 = Unterfunktion(y);
Byte3 = Unterfunktion(z);
Byte4 = Unterfunktion(a);

return Variable_K = (Byte4<<24)+(Byte3<<16)+(Byte2<<8)+Byte1;
}

if(((Funktion(h,j))>>16) == 0xA1B2)
{

}

So funktioniert es auch. Ich finde aber den Ansatz von Thomas Eckmann 
auch ganz gut. Nach meinem Verständnis von dem was ich gerne haben 
möchte, müsste das ja wie folgt aussehen:

XXXX  Funktion(q,w)
{
char nByte[4] = {0x11, 0x22, 0x33, 0x44};
int* nX = (int*) nByte;
short* nSlow = (short*) nByte;
short* nShigh = (short*) (nByte + 2);

   nByte[0] = Unterfunktion(x);
   nByte[1] = Unterfunktion(y);
   nByte[2] = Unterfunktion(z);
   nByte[3] = Unterfunktion(a);

return QQQQ;
}

Meine Frage ist jetzt, wie müsste der Rückgabetyp und Returnwert 
definiert sein, damit ich nach dem Funktionsaufruf bespw.:

if(*nShigh == 0xA1B2){}

durchführen kann?

von Volkmar D. (volkmar)


Lesenswert?

Joey T. schrieb:
> return Variable_K = (Byte4<<24)+(Byte3<<16)+(Byte2<<8)+Byte1;

Bist Du sicher, daß das funktioniert? Ich vermute daß der Rückgabewert 
immer kleiner als 65536 ist. Die Rechenoperationen werden auf int 
durchgeführt und da ergeben Schiebeoperationen mit 16 oder mehr Bits 
immer 0.

Du müsstest die einzelnen Variablen schon auf long casten, damit es 
korrekt ist.

von Volkmar D. (volkmar)


Lesenswert?

Volkmar Dierkes schrieb:
> Bist Du sicher, daß das funktioniert? Ich vermute daß der Rückgabewert
> immer kleiner als 65536 ist. Die Rechenoperationen werden auf int
> durchgeführt und da ergeben Schiebeoperationen mit 16 oder mehr Bits
> immer 0.
>
> Du müsstest die einzelnen Variablen schon auf long casten, damit es
> korrekt ist.

Nehme meine Aussage zurück. War zusehr auf AVR fixiert, da Du im Forum 
PC-Programmierung gepostet hast, nehme ich mal an, das dort 
standardmäßig nicht mit int sondern long gerechnet wird, und dann tritt 
der Fehler nicht auf.

von Thomas E. (thomase)


Lesenswert?

Joey T. schrieb:
> Meine Frage ist jetzt, wie müsste der Rückgabetyp und Returnwert
> definiert sein, damit ich nach dem Funktionsaufruf bespw.:

char nByte[4] = {0x11, 0x22, 0x33, 0x44};
int* nX = (int*) nByte;
short* nSlow = (short*) nByte;
short* nShigh = (short*) (nByte + 2);

void Funktion(<Para>)
{
   nByte[0] = Unterfunktion(x);
   nByte[1] = Unterfunktion(y);
   nByte[2] = Unterfunktion(z);
   nByte[3] = Unterfunktion(a);
}

Das Byte-Array wird global angelegt und der Zugriff erfolgt dann mit 
verschiedenen Pointern immer auf die gleiche Speicherstelle. Je nach 
Pointertyp können dann 1, 2 oder 4 Bytes gelesen werden. Um mit nShigh 
auf Byte 2 und 3 zuzugreifen, muß der Pointer dann um 2 erhöht werden.
Die Daten werden einfach ins globale Array geschrieben und sind auch nur 
einmal vorhanden. Deshalb hat die Funktion, die die Daten mit 
Unterfunktion() abholt, auch keinen Rückgabewert.
Du kannst das Byte-Array aber auch als Parameter an Funktion() 
übergeben. Dann kann dieses in der aufrufenden Funktion lokal angelegt 
sein.
void Funktion(<Para>, char* nArray)
{
...
}

In Funktion() darfst du das nicht packen, da die Variable nByte, die 
einzige Variable, die angelegt wird, auf dem Stack liegt und nach 
Beendigung der Funktion nicht mehr da ist.

Volkmar Dierkes schrieb:
> Die Rechenoperationen werden auf int
> durchgeführt und da ergeben Schiebeoperationen mit 16 oder mehr Bits
> immer 0.
Ich gehe davon aus, daß das ein 32-Bit Rechner ist, bei dem int 32 Bit 
lang ist. Sonst muß man natürlich statt int long nehmen.

mfg.

von Rolf Magnus (Gast)


Lesenswert?

Volkmar Dierkes schrieb:
> Die Rechenoperationen werden auf int durchgeführt und da ergeben
> Schiebeoperationen mit 16 oder mehr Bits immer 0.

Das kommt auf die Größe von int an. Joey ist etwas inkonsistent, was 
seine Angaben betrifft. Einerseits postet er unter "PC-Programmierung", 
andererseits schreibt er von einem Tasking-Compiler. Die Zielarchitektur 
fehlt, oder hab ich sie nur übersehen?
Wie dem auch sei: Bei diesem Compiler kann sizeof(int) unterschiedlich 
groß sein, je nach Prozessor.
Prinzipiell ist der Cast aber eine gute Idee, denn dann geht's mit jeder 
Architektur.

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
Noch kein Account? Hier anmelden.