mikrocontroller.net

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


Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
erstens Zeiger lernen, zweitens die Suchfunktion benutzen - das
Thema gibt es hier etwa 15456 mal.
    char carr[2];
    carr[0] = ((char *)&intarr[i])[0];
    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.

Autor: Stefan Hennig (stefanhennig)
Datum:

Bewertung
0 lesenswert
nicht 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:
int aiIrgendwas[NUM_EL_INT];
char pcMirGraust = (char*)aiIrgendwas;

aiIrgendwas[0] = 4711;
/* 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:
#include "MISRATYPES.H" /* Oder wie auch immer das in Deiner Welt heisst */

int16_t ai16Irgendwas[NUM_EL_INT];
uint8_t  au8Serialisiert[NUM_EL_INT*2];

for (int i=0; i<MUM_EL_INT; ++i)
{
  au8Serialisiert[i*2]   = (uint8_t)(ai16Irgendwas[i]&0xFF);
  au8Serialisiert[i*2+1] = (uint8_t)(ai16Irgendwas[i]>>8);
}

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

stdint.h heisst das normgerecht.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stefan Hennig schrieb:
> Ich lebe ja davon derartige Schlampigkeiten zu suchen.

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

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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ß.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Hennig (stefanhennig)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht 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.
union {
 int int_v;
 short short_v;

 struct {
  char low;
  char high;
 } char_v;

} converter;

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

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klaus Wachtler schrieb:
> unsigned char c[sizeof(int)];

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

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hoppla danke :)

Autor: Tim T. (tim_taylor)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jakob (Gast)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: S.H. aus B. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hätte ich dir auch sagen können Jakob.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oben im Quelltext:
#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.

Autor: Jakob (Gast)
Datum:

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

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kenne die Grundlagen von C und habe meine Schwierigkeiten damit.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
__int16 für MS VS

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

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

Dann kennst du dir Grundlagen nicht genug :-)

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Loonix (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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? ;)

Autor: Loonix (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jakob schrieb:
> Ich kenne die Grundlagen von C

dann sind deine Grundlagen nicht grundlagig genug.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi hab noch ne Menge fragen :)
#include <stdio.h>

__int16 werte[100];
int n;
char test[10];

int main()
{
  for (n=0; n<100; n++)
  {
    werte[n]=n;
  }

  werte[3]=16384;
  werte[4]=-16384;

  test[0]=((char *) &werte[3])[0];


printf("%x\n", werte[0]);
printf("%x\n", werte[1]);
printf("%x\n", werte[2]);
printf("%x\n", werte[3]);
printf("%x\n", werte[4]);
printf("%x\n", test[0]);

getchar();
}

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] ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :)

Autor: Arc Net (arc)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab mich nochmal durch die Grundlagen geforstet. Ich will ja immer noch 
ein Array mit Bytes haben. Sollte C++ sein :)
struct array2byte
{
unsigned char high;
unsigned char low;
}

struct array10byte
{
array2byte array[3];
}

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

Autor: Jakob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
array[5] natürlich

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja, hast du.

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.