Forum: PC-Programmierung Bytes auslesen und in ein Array schreiben "C"


von Jakob (Gast)


Lesenswert?

Hallo Leute!

Ich habe ein Int-Array das ist z. B. so gefüllt ist 
[10000;-10000;5000;-2344;...;x]

Nun zu meinem Problem. Der Int-Datentyp besteht doch aus 2 Byte. Ich 
möchte nun die zwei Bytes aus dem Int-Array ausgewählter Zahlen auslesen 
und in ein char-Array schreiben.

Ich vermute man macht das am besten mit Zeigern, aber damit kenne ich 
mich noch nicht so gut aus.

Würde mich über einen Hinweis freuen.
mfg Jakob

von Klaus W. (mfgkw)


Lesenswert?

erstens Zeiger lernen, zweitens die Suchfunktion benutzen - das
Thema gibt es hier etwa 15456 mal.
1
    char carr[2];
2
    carr[0] = ((char *)&intarr[i])[0];
3
    carr[1] = ((char *)&intarr[i])[1];

Jakob schrieb:
> [10000;-10000;5000;-2344;...;x]

Das ist aber kein C.

Jakob schrieb:
> Der Int-Datentyp besteht doch aus 2 Byte.

Kann sein, muß nicht - je nach Compiler.

von Stefan H. (stefanhennig)


Lesenswert?

Jetzt verrat mir mal einer, warum hier zum Teufel immer verquastere und 
implementationsabhängigere Codevarianten auf so ein gängiges Problem 
losgelassen werden. Wieviele Gigabytes musst Du denn pro Sekunde 
umkodieren?

Wenn es absolut auf Geschwindigkeit ankommt, dann doch gleich jede Scham 
über Bord geworfen und so:
1
int aiIrgendwas[NUM_EL_INT];
2
char pcMirGraust = (char*)aiIrgendwas;
3
4
aiIrgendwas[0] = 4711;
5
/* pcMirGraust[0] und pcMirGraust[1] können Daten enthalten, die was mit 4711 zu tun haben */

Wenn Du irgendwie Kontrolle über das behalten willst was Du da tust, 
solltest Du so etwas tun:
1
#include "MISRATYPES.H" /* Oder wie auch immer das in Deiner Welt heisst */
2
3
int16_t ai16Irgendwas[NUM_EL_INT];
4
uint8_t  au8Serialisiert[NUM_EL_INT*2];
5
6
for (int i=0; i<MUM_EL_INT; ++i)
7
{
8
  au8Serialisiert[i*2]   = (uint8_t)(ai16Irgendwas[i]&0xFF);
9
  au8Serialisiert[i*2+1] = (uint8_t)(ai16Irgendwas[i]>>8);
10
}

Das ist wenigstens soweit durchschaubar, Du weißt immerhin, wo High- und 
wo Low-Byte stehen, etc. Aber natürlich ist der Code a) lesbar und b) 
nicht superperformant, also überhaupt kein richtiges C sondern nur 
verkleidetes Pascal...

Aber das schreib ich nur, weil ich weiß, dass es keinen interessiert. 
Ich lebe ja davon derartige Schlampigkeiten zu suchen.

Grüße,
  Stefan

von Klaus W. (mfgkw)


Lesenswert?

Stefan Hennig schrieb:
> #include "MISRATYPES.H" /* Oder wie auch immer das in Deiner Welt heisst */

stdint.h heisst das normgerecht.

von Klaus W. (mfgkw)


Lesenswert?

Stefan Hennig schrieb:
> Jetzt verrat mir mal einer, warum hier zum Teufel immer verquastere und
> implementationsabhängigere Codevarianten

Über Geschmack kann man streiten.
Aber erstens wollte der TO eine Zeigerlösung haben, zweitens: wo
bitte ist das (von der Vorgabe sizeof(int)==2 abgesehen)
implementationsabhängig?

Stefan Hennig schrieb:
> Wenn es absolut auf Geschwindigkeit ankommt, dann doch gleich jede Scham
> über Bord geworfen und so:int aiIrgendwas[NUM_EL_INT];
> char pcMirGraust = (char*)aiIrgendwas;
>
> aiIrgendwas[0] = 4711;
>

So wird es jedenfalls nicht gehen, was deine Abneigung gegen
Zeiger natürlich bestätigt :-)

von Klaus W. (mfgkw)


Lesenswert?

Stefan Hennig schrieb:
> Ich lebe ja davon derartige Schlampigkeiten zu suchen.

Das nehme ich natürlich persönlich :-)

von Jakob (Gast)


Lesenswert?

Nun habt ihr mich etwas verwirrt.

also warum sollte der int in C nicht 2 Byte lang sein?
Und ja es soll eine schnelle Methode sein, da sind doch Zeiger genau 
richtig oder nicht?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Jakob schrieb:
> also warum sollte der int in C nicht 2 Byte lang sein?

Weil er es auf 32-Bit-Systemen (ARM, x86 etc.) nicht ist, da ist ein int 
4 i.d.R. vier Bytes groß.

von Klaus W. (mfgkw)


Lesenswert?

Und Stefan hat da vollkommen recht:
Wenn man sich auf 2 Bytes verlässt, dann ist int16_t
bzw. uint16_t der richtige Typ.

von Stefan H. (stefanhennig)


Lesenswert?

Klaus Wachtler schrieb:
> Stefan Hennig schrieb:
>> Ich lebe ja davon derartige Schlampigkeiten zu suchen.
>
> Das nehme ich natürlich persönlich :-)

Danke für das Smiley. Persönlich wars bestimmt nicht gemeint.

Mein Beispielcode ist natürlich falsch, mindestens fehlt ein 
Pointer-Stern.
Ansonsten bitte ich, meine unterschwellige Gereiztheit zu entschuldigen, 
ich bin im Moment neben dem üblichen Weihnachtsstress noch im 
Projektstress, der sich zumindest etwas hätte abmildern lassen, wenn 
jeder, sagen wir, etwas defensiver programmiert hätte und nicht immerzu 
irgendwelche Annahmen über irgendetwas gemacht hätte, das im vor-vorigen 
Projekt wahr gewesen sein mochte.

Nichts für ungut,
   Stefan.

von Klaus W. (mfgkw)


Lesenswert?

Habe ich auch nicht so ernst genommen, aber Pfusch lasse ich
auch nicht gerne auf mir sitzen.
Sonst bin ich nicht eitel, aber da manchmal schon (was nicht
davor schützt, trotzdem Fehler zu machen - leider).

Defensives Programmieren kann ich aber auch jederzeit unterstützen,
dagegen sage ich gar nichts.

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Wie wäre denn eine Lösung mit Union?

Dabei ist es egal ob ein int jetzt 2, 4 oder 8 Byte groß ist, solange 
die Byteorder Little-Endian ist.
1
union {
2
 int int_v;
3
 short short_v;
4
5
 struct {
6
  char low;
7
  char high;
8
 } char_v;
9
10
} converter;

Wobei ich auch hier Datentypen mit vorgegebener Größe bevorzugen würde, 
also int16_t bzw. int8_t.

von Klaus W. (mfgkw)


Lesenswert?

Oder umgekehrt wenn es denn int sein soll:
1
    union
2
    {
3
        int           i;
4
        unsigned char c[sizeof(int)];
5
    } int_oder_char;
6
    int_oder_char.i = 4711;
7
    // in int_oder_char.c[0] bis int_oder_char.c[sizeof(int)-1] stehen jetzt die Bytes

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Klaus Wachtler schrieb:
1
> unsigned char c[sizeof(int)];

Das ist natürlich sehr elegant und gegebüber dem struct zu bevorzugen!

von Jakob (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> char carr[2];
>     carr[0] = ((char *)&intarr[i])[0];
>     carr[1] = ((char *)&intarr[i])[1];


Hallo ich habe das so gemacht und er gibt mir ein Herz :) aus. Ich 
dachte da kommt irgendwie eine Hexzahl heraus?

Dem Problem mit der Bytelänge bei int, kann ich doch umgehen wenn ich 
einfach short nehme oder?

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Du musst dir schon überlegen wie du den char ausgibst:

printf("%c", chrr[0]); -> Zeigt dir das Ascii Zeichen an (das Herz).

printf("%d", chrr[0]); -> Zeigt dir den Dezimalwert an.

printf("%x", chrr[0]); -> Zeigt dir den Hexadezimalwert an.

von Jakob (Gast)


Lesenswert?

hoppla danke :)

von Tim T. (tim_taylor) Benutzerseite


Lesenswert?

Und tu dir bitte den Gefallen und benutze definierte Datentypgrößen 
(int16_t).

Bei einem int und short ist nur sicher das sie mindestens 16 Bit haben, 
sowie das ein long mindestens so groß ist wie ein int, aber mindestens 
32 Bit hat.

Daraus hat sich auf 16-Bit Systemen die Praxis eingebürgert char, short, 
int und long die Größen 8, 16, 16, 32 zu geben; auf 32-Bit Systemen 
jedoch 8, 16, 32, 32.

Aber drauf verlassen das ein short oder int jetzt 16 oder 32 Bit hat, 
kannst du dich nicht!

von Karl H. (kbuchegg)


Lesenswert?

Und schon gar nicht, unter keinen Umständen, nimmt man den Datentyp 
'char' her, wenn man mit Bytes arbeitet!


Am besten gewöhnt man sich von vrne herein gleich mal die Sichtweise an, 
dass es in C 3 verschiedene Character-Datentypen gibt


    char
    signed char
    unsigned char


Aber auch hier bevorzugt man für die letzten beiden die Schreibweise 
int8_t bzw uint8_t

von Jakob (Gast)


Lesenswert?

ich würde gerne mit uint16_t arbeiten, aber mein compiler kennt das 
nicht

von Klaus W. (mfgkw)


Lesenswert?

Jakob schrieb:
> ich würde gerne mit uint16_t arbeiten, aber mein compiler kennt das
> nicht

Auch nicht mit stdint.h?

Dann definiere es dir selber an einer Stelle und schreibe den Rest ohne 
int.

von Klaus W. (mfgkw)


Lesenswert?

Karl heinz Buchegger schrieb:
> Am besten gewöhnt man sich von vrne herein gleich mal die Sichtweise an,
> dass es in C 3 verschiedene Character-Datentypen gibt
>
>
>     char
>     signed char
>     unsigned char

Hast du das schon auf einer Funktionstaste liegen?
Irgendwie kommt es mir bekannt vor :-)

von S.H. aus B. (Gast)


Lesenswert?

Hätte ich dir auch sagen können Jakob.

von Jakob (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Auch nicht mit stdint.h?
>
>
>
> Dann definiere es dir selber an einer Stelle und schreibe den Rest ohne
>
> int.

auch mit dem stdint.h nicht.
Wie stelle ich das an?

von Klaus W. (mfgkw)


Lesenswert?

Oben im Quelltext:
1
#include <stdint.h>

Und ab dann munter int8_t, uint8_t, int16_t, uint32_t, int32_t, uint32_t 
... verwenden.

Wenn das nicht geht, würde ich gerne wissen, mit welchem Conmpiler es 
nicht gehen soll.

von Jakob (Gast)


Lesenswert?

habe ich gemacht, vllt hab ich die Datei nicht auf dem Rechner!? Hab MS 
Visual Studio 2005

von Klaus W. (mfgkw)


Lesenswert?

Bevor du übrigens mit ganz wilden Konstruktionen liebäugelst,
wäre es förderlich, auch mal die Grundlagen von C anzuschauen.
Das erspart allen Beteiligten viel Arbeit, auch dir.

von Peter (Gast)


Lesenswert?

Jakob schrieb:
> habe ich gemacht, vllt hab ich die Datei nicht auf dem Rechner!? Hab MS
> Visual Studio 2005

dann musst du glaube ich _int16 verwenden.

von Jakob (Gast)


Lesenswert?

Ich kenne die Grundlagen von C und habe meine Schwierigkeiten damit.

von Jakob (Gast)


Lesenswert?

__int16 für MS VS

von Klaus W. (mfgkw)


Lesenswert?

Es gibt einen besseren Weg:
stdint.h ist bei VS2005 tatsächlich nichtz mit in der Installation, man 
kann es aber nachrüsten:
http://msinttypes.googlecode.com/svn/trunk/stdint.h

Diese Datei zu den anderen Include-Dateien kopieren und es sollte gehen.

von Klaus W. (mfgkw)


Lesenswert?

Jakob schrieb:
> Ich kenne die Grundlagen von C und habe meine Schwierigkeiten damit.

Dann kennst du dir Grundlagen nicht genug :-)

von Klaus W. (mfgkw)


Lesenswert?

Klaus Wachtler schrieb:
> Diese Datei zu den anderen Include-Dateien kopieren und es sollte gehen.

Nachtrag: bei der Gelegenheit kann man auch gleich
http://msinttypes.googlecode.com/svn/trunk/inttypes.h
dazukopieren.

von Loonix (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Defensives Programmieren

Leider klingt das so langweilig, dass Jungspunden (ok, ist 
Ansichtssache) wie mir dabei die Füsse einschlafen ;)
Könnt ihr alten Hasen da vielleicht ein "cooleres" Wort für finden?

Klaus Wachtler schrieb:
> Bevor du übrigens mit ganz wilden Konstruktionen liebäugelst,

DAS klingt doch schon viel reizvoller, wer möchte nicht Beherrscher 
"wilder Konstrukte" sein? ;)

von Loonix (Gast)


Lesenswert?

@Jakob

Sorry, mein Beitrag ist sicher keine große Hilfe für dich gewesen.

Klaus Wachtler schrieb:
> Jakob schrieb:
>> Ich kenne die Grundlagen von C und habe meine Schwierigkeiten damit.
>
> Dann kennst du dir Grundlagen nicht genug :-)
>

Damit hat Klaus aber das Wesentliche gesagt. Wenn dann noch Fragen 
auftauchen, immer her damit.

von Karl H. (kbuchegg)


Lesenswert?

Jakob schrieb:
> Ich kenne die Grundlagen von C

dann sind deine Grundlagen nicht grundlagig genug.

von Jakob (Gast)


Lesenswert?

Hi hab noch ne Menge fragen :)
1
#include <stdio.h>
2
3
__int16 werte[100];
4
int n;
5
char test[10];
6
7
int main()
8
{
9
  for (n=0; n<100; n++)
10
  {
11
    werte[n]=n;
12
  }
13
14
  werte[3]=16384;
15
  werte[4]=-16384;
16
17
  test[0]=((char *) &werte[3])[0];
18
19
20
printf("%x\n", werte[0]);
21
printf("%x\n", werte[1]);
22
printf("%x\n", werte[2]);
23
printf("%x\n", werte[3]);
24
printf("%x\n", werte[4]);
25
printf("%x\n", test[0]);
26
27
getchar();
28
}

Die Ausgabe macht:
0    //ja alles klar
1    //ja alles klar
2    //ja alles klar
4000 //ja alles klar
FFFFC000 //nein ich erwarte C000 2Byte das sind 4 Byte !?
0    //ich erwarte 4000

Warum klappt das nicht bei werte[4] und test[0] ?

von Karl H. (kbuchegg)


Lesenswert?

Jakob schrieb:

> 4000 //ja alles klar
> FFFFC000 //nein ich erwarte C000 2Byte das sind 4 Byte !?

Das ist aber printf egal.
printf erwartet bei %x einen int. Und ein int ist auf deinem PC nun mal 
4 Bytes groß


> 0    //ich erwarte 4000

Solange du das weiter oben Gesagte über den Datentyp char nicht 
beherzigst wird das nichts. Des weiteren wirst du mit 4000 in einem Byte 
sowieso Schiffbruch erleiden. 256 ist das Maximum.

von Klaus W. (mfgkw)


Lesenswert?

... , was bedeutet daß deine 2 Byte ausgegeben werden zusammen
mit 2 Byte, die gerade im Weg stehen (direkt daneben), bzw. deine
2 Byte auf 4 aufgeblasen werden.

von Jakob (Gast)


Lesenswert?

ja stimmt das ist nicht richtig mit Byte und der 4000.
Ich wälze mich mal durch die Grundlagen. Wenn ich irgendwo hänge frage 
ich halt noch mal nach :)

von Arc N. (arc)


Lesenswert?

Karl heinz Buchegger schrieb:
> Jakob schrieb:
>> 0    //ich erwarte 4000
>
> Solange du das weiter oben Gesagte über den Datentyp char nicht
> beherzigst wird das nichts. Des weiteren wirst du mit 4000 in einem Byte
> sowieso Schiffbruch erleiden. 256 ist das Maximum.

Das würde hier noch passen: ein Byte ist 0, dass andere 64.

An den TO: Null kommt raus, da die Byte-Reihenfolge nicht Big-Endian, 
sondern Little-Endian ist d.h. ((char *) &werte[3])[1] == 0x40

von Jakob (Gast)


Lesenswert?

hab mich nochmal durch die Grundlagen geforstet. Ich will ja immer noch 
ein Array mit Bytes haben. Sollte C++ sein :)
1
struct array2byte
2
{
3
unsigned char high;
4
unsigned char low;
5
}
6
7
struct array10byte
8
{
9
array2byte array[3];
10
}

Jetzt hab ich doch ein Array mit wo ich schön 10 Byte reinschreiben kann 
oder?

von Jakob (Gast)


Lesenswert?

array[5] natürlich

von Klaus W. (mfgkw)


Lesenswert?

ja, hast du.

Ob das alles Sinn macht, bezweifle ich bauchmäßig irgendwie, aber danach
hattest du nicht gefragt.

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.