Arbeit mit 16 bit in 32 bit system in C

#793280
Lesenswert?

Hallo Leute,

ich habe ein 32 bit System. Wie kann ich mit 16 bit auf diese System 
zugreifen(in C)

z.B

ich habe folgende Daten paket:
1.Teil besteht aus 6 byte
2.Teil besteht aus 4 byte
3.Teil besteht wieder auf 6 byte
4.Teil besteht aus 6 byte
und ich muss diese Teil kontrolieren
es wäre günstiger(meine Meinung nach) wenn ich mit 16 bit arbeiten kann.
hat jermand eine Vorschalg wie ich das ambesten machen kann?

Danke für euere Hilfe
Grüße
Julietta
Gast #793311
Lesenswert?

In stdint.h sind bei neueren Compilern Intertypen mit konkreten Größen
deklariert, z.B. int8_t, uint8_t, int32_t, uint32_t usw.

Wenn dein Prozessor überhaupt 16-Bit-Speicherzugriffe unterstützt,
gibt es auch int16_t und uint16_t. Probier's aus.
#795476
Lesenswert?

z.B ich habe folgende Code:
1
#include<stdio.h>
2

3
typedef short int int16;
4
typedef long int int32;
5
int main(){
6
FILE *data_fp;
7
int32 datain32[100];
8
int16 datain16[100];
9
int32 *ptr32;
10
int16 *ptr16;
11
data_fp = fopen(".../datain.dat","r");
12
int i;
13
//wenn ich diese Loesung benutze dann kann ich die Daten lesen 
14
//und bekomme auch die richtige Ergebnis beim Test. Aber mein Problem wie
15
 //gesagt ist nur dass ich manchmals mit 16 Bit arbeiten muss 
16

17
if(data_fp != NULL){
18
for(i=0;i<7;i++)
19
fscanf(data_fp,"%8x",datain32[i]);
20
}
21
ptr32 = datain32
22
}
23

24
/*
25
Wenn ich mit 16 bit pointer wie folge benutze dann bekomme ich nur falsche Ergebnisse
26
*/
27
if(data_fp != NULL){
28
for(i=0;i<14;i++)
29
fscanf(data_fp,"%4x",datain16[i]);
30
}
31
ptr16 = datain32
32
}

so sieht mein Ergebnis aus wenn ich das ausgebe
datain32[0]:30aa3000   ptr32:30aa3000
datain16[0]:0          ptr16:0

datain32[1]:31bb3000   ptr32:31bb3000
datain16[0]:0          ptr16:0

datain32[0]:32cc3000   ptr32:32cc3000
datain16[0]:ffff8838   ptr16:ffff8838

datain32[0]:33dd3000   ptr32:33dd3000
datain16[0]:ffffb7f3   ptr16:ffffb7f3
Persönliche Seite #795565
Lesenswert?

Du bist Dir sicher, daß diese Codezeile funktioniert?

   fscanf(data_fp,"%8x",datain32[i]);

Enthält das Array datain32 etwa Pointer? Dann ist es falsch deklariert.

(f)scanf erwartet als Argumente die Adressen der Objekte, in denen die 
gelesenen Daten abgelegt werden soll, %x erwartet einen int-Pointer.

datain[irgendwas] aber ist vom Typ int32.

Besser wirds mit

   fscanf(data_fp, "%8x", datain32 + i);

Das zweite Problem ist, daß (f)scanf eben durch %x dazu veranlasst wird, 
einen int-Pointer zu erwarten, egal, welche Feldbreite angegeben ist - 
Du musst also einen anderen Formatspezifizierer angeben, um einen short 
int zu lesen. Der lautet %hx

Also


   fscanf(data_fp, "%4hx", datain16 + i);
Persönliche Seite #796414
Lesenswert?

Das würde bedeuten, daß Deine scanf-Implementierung kaputt ist oder aber 
daß Deine Datei, wie auch immer sie aufgebaut sein mag, nicht korrekt 
gelesen wird.

Poste mal sowohl deinen aktuellen Quelltext als auch ein Muster für so 
eine Datei, wie Du sie einzulesen versuchst.

Hast Du Dir mal im Debugger angesehen, was geschieht?

Wie verarbeitest Du die auf Deine Art und Weise bestimmten Pointer, wie 
erzeugst Du die Ausgaben, die Du in Deinem Beitrag von gestern, 14:12 
angegeben hast?
#797515
Lesenswert?

hier ist mein code
1
#include<stdio.h>
2

3
typedef short int int16;
4
typedef long int int32;
5
int main(){
6
FILE *data_fp;
7
int32 datain32[100];
8
int16 datain16[100];
9
int32 *ptr32;
10
int16 *ptr16;
11
data_fp = fopen(".../datain.dat","r");
12
int i;
13
//wenn ich diese Loesung benutze dann kann ich die Daten lesen 
14
//und bekomme auch die richtige Ergebnis beim Test. Aber mein Problem wie
15
 //gesagt ist nur dass ich manchmals mit 16 Bit arbeiten muss 
16

17
  if(data_fp != NULL){
18
    for(i=0;i<7;i++)
19
       fscanf(data_fp,"%8x",&datain32[i]);
20
/*
21
Wenn ich mit 16 bit pointer wie folge benutze dann bekomme ich nur falsche Ergebnisse
22
*/
23
    for(i=0;i<14;i++)
24
       fscanf(data_fp,"%4x",&datain16[i]);//oder "%4hx"
25
  }
26
for(i=0;i<4;i++){
27
   printf("datain32%d:%x\t",i,datain32[i]);
28
   printf("datain16%d:%x\t",i,datain16[i]);
29
return 0;
30
}
datain32[0]:30aa3000               datain16[0] = 0
datain32[0]:31bb3000               datain16[0] = 0
datain32[0]:32cc3000               datain16[0] = 7838
datain32[0]:33ee3000               datain16[0] = ffffb7fb


hier sind meine Daten in datain.dat
30aa300031bb300032cc300033ee3000
#797529
Lesenswert?

Julietta Ohara wrote:

>        fscanf(data_fp,"%8x",&datain32[i]);
> /*
> Wenn ich mit 16 bit pointer wie folge benutze dann bekomme ich nur
> falsche Ergebnisse
> */
>     for(i=0;i<14;i++)
>        fscanf(data_fp,"%4x",&datain16[i]);//oder "%4hx"

x kann nicht gleichzeitig der Format-specifier für
int32_t und int16_t sein. Da muss es einen Unterschied
geben.

Der Format specifier muss ja gleichzeitig codieren, in welcher
Form die Daten eingelesen werden sollen (als Hex-Zahlen) und
er muss codieren welchen Datentyp die Variable hat, die das
eingelesene aufnehmen soll.

Sieh dir mal dies hier an
http://www.nongnu.org/avr-libc/user-manual/group__avr__inttypes.html
an schau auf deinem System nach, ob du eine inttypes.h hast.
1
    for(i=0;i<7;i++)
2
       fscanf(data_fp,"%8"SCNx32 ,&datain32[i]);
3

4
    // das ganze mit int16_t
5

6
    for(i=0;i<14;i++)
7
       fscanf(data_fp,"%4"SCNx16 ,&datain16[i]);
8
  }
Persönliche Seite #797570
Lesenswert?

Der Formatspezifierer ist in der Tat das Problem. Welcher hier zu 
verwenden ist, habe ich bereits erwähnt, %hx anstelle von %x.

Die Konstanten SCNx32 und SCNx16 im verlinkten Dokument (der avr-libc) 
sind nur auf 16-Bit-Systemen zu brauchen, denn
1
#define   SCNx16   "x"
2
#define   SCNx32   "lx"
setzt "16" mit "int" gleich. Und das funktioniert auf einem 
32-Bit-System nicht, da dort sizeof (int) != 2 ist.

Im hier vorliegenden Fall könnte es sinnvoller sein, zunächst den 
"Datenstrom" der Datei in 4-Byte/Zeichen-Häppchen zu zerlegen und diese 
dann (s)scanf zu übergeben.
Allerdings muss auch hier der korrekte Formatspezifizierer verwendet 
werden, damit (s)scanf auch den übergebenen Pointer als short-Pointer 
benutzt.

Ich bezweifle allerdings ein bisschen, daß hier auch wirklich der 
verwendete Code gepostet wird, denn die Zeilen
1
for(i=0;i<4;i++){
2
   printf("datain32%d:%x\t",i,datain32[i]);
3
   printf("datain16%d:%x\t",i,datain16[i]);
4
return 0;
5
}

sind so a) gar nicht übersetzbar (da fehlt 'ne Klammer) und können b) 
die Ausgabe
1
datain32[0]:30aa3000               datain16[0] = 0
2
datain32[0]:31bb3000               datain16[0] = 0
3
datain32[0]:32cc3000               datain16[0] = 7838
4
datain32[0]:33ee3000               datain16[0] = ffffb7fb

nicht erzeugt haben.

Daher ist, solange von "Julietta" nicht mit offenen Karten gespielt 
wird, weiteres Rätselraten angesagt.
Gast #797571
Lesenswert?

Bin zwar kein C Crack mehr, aber mir ist Folgendes aufgefallen. 
Vielleicht ist es ja hilfreich.

 Mit fscanf kann so nicht gearbeitet werden, denn es erwartet bei %x 
Format einen Speicherplatz für ein int als Argument.
 16 Bit haben im Programm 4 Bytes und 32 Bit haben 8 Bytes?
 Der Filepointer wird nicht zurückgespult.
 Der zweite Index sollte bis 15 laufen, wenn der erste bis 7 läuft.

Um die Ergebnisse zu überprüfen, könnte man beide Arrays vielleicht 
Byteweise ausgeben (unsigned char).
#797584
Lesenswert?

Rufus t. Firefly wrote:
> Der Formatspezifierer ist in der Tat das Problem. Welcher hier zu
> verwenden ist, habe ich bereits erwähnt, %hx anstelle von %x.
>
> Die Konstanten SCNx32 und SCNx16 im verlinkten Dokument (der avr-libc)
> sind nur auf 16-Bit-Systemen zu brauchen, denn
>
1
> #define   SCNx16   "x"
2
> #define   SCNx32   "lx"
3
>
> setzt "16" mit "int" gleich. Und das funktioniert auf einem
> 32-Bit-System nicht, da dort sizeof (int) != 2 ist.

Ja. Das ist schon klar. Deshalb habe ich ihr ja auch nahegelegt
auf ihrem System nach inttypes.h zu suchen. Da müssten die
korrekten Codes drin sein.
So wie ich die angegebene Site interpretiere, ist inttypes.h
ein Standard-Header, der eigentlich verfügbar sein sollte.
Damit kommt man gut um das leidige Thema 'auf meinem System
heissen die Format specifier aber anders' herum.
(Wusste bisher auch nicht, das es so einen Header gibt :-)


> Ich bezweifle allerdings ein bisschen, daß hier auch wirklich der
> verwendete Code gepostet wird, denn die Zeilen

Da hast du recht.

Aber auch hier wieder: Auch bei printf kann der Format
specifier für einen int32_t und einen int16_t nicht
derselbe sein.

> Daher ist, solange von "Julietta" nicht mit offenen Karten gespielt
> wird, weiteres Rätselraten angesagt.

Ich denke, das Hauptproblem ist ein fehlendes Verständnis dafür,
was es mit dem Format Specifier auf sich hat.
'Ich will hex-Ausgabe mit 4 Zeichen und deshalb schreibe ich %4x'
ist halt zuwenig.
Persönliche Seite #797589
Lesenswert?

>  Mit fscanf kann so nicht gearbeitet werden, denn es erwartet bei %x
>  Format einen Speicherplatz für ein int als Argument.

Das ist es ja, was ich bereits mehrfach angesprochen habe, und was auch 
Karl Heinz meinte, wenn auch er irrigerweise von einem 16-Bit-System 
ausgegangen war.


Wenn aus welchen Gründen auch immer "Julietta" nicht in der Lage sein 
sollte, 16-Bit-Werte via (s)scanf aus einer Textdatei einzulesen, dann 
ließe sich natürlich auch eine andere Vorgehensweise wählen:
1
#include<stdio.h>
2

3
typedef short int int16;
4
typedef long int int32;
5
int main()
6
{
7
  FILE *data_fp;
8
  int32 wert32;
9
  int16 datain16[100];
10
  int16 *ptr16;
11
  data_fp = fopen(".../datain.dat","r");
12
  int i;
13

14
  if (data_fp != NULL)
15
  {
16
    for (i = 0; i < 7; i++)
17
    {
18
      fscanf(data_fp, "%8x", &wert32);
19
      datain16[i * 2] = (int16) ((wert32 >> 16) & 0xffff);
20
      datain16[i * 2 + 1] = (int16) (wert32 & 0xffff);
21
    }
22

23
  for(i = 0; i < 4; i++)
24
  {
25
    printf("datain16[%d]:%x\t", i, (int) datain16[i]);
26
  }
27
  return 0;
28
}

Das ist natürlich 'ne heikle Angelegenheit, bei der die endianness der 
Zielmaschine berücksichtigt werden muss. Angegeben ist die Intel-Sicht 
der Welt.
#797592
Lesenswert?

Rufus t. Firefly wrote:
>>  Mit fscanf kann so nicht gearbeitet werden, denn es erwartet bei %x
>>  Format einen Speicherplatz für ein int als Argument.
>
> Das ist es ja, was ich bereits mehrfach angesprochen habe, und was auch
> Karl Heinz meinte, wenn auch er irrigerweise von einem 16-Bit-System
> ausgegangen war.

Nein. Überhaupt nicht.
Ich such nur nach einem Weg, wie man das systemunabhängig (16 oder 32)
formulieren kann.
Und dabei bin ich auf dieses (anscheinend Standard-) Header File
gestossen, welches das Problem eigentlich sauber lösen sollte.

Julietta darf natürlich nicht einfach nur die Codes aus dem Link
übernehmen, sondern muss das mitgelieferte inttypes.h benutzen.
Dann sollte sich das 'Problem' eigentlich in Luft auflösen.

Ich kann mir nicht vorstellen, dass irgendein Compilerhersteller
gerade bei scanf und Konsorten irgendwelche Probleme in seiner
Library hat. Das Problem liegt meines Erachtens mit Sicherheit
an einem falschen Code im Format Specifier.
Persönliche Seite #797628
Lesenswert?

> Nein. Überhaupt nicht.
> Ich such nur nach einem Weg, wie man das systemunabhängig (16 oder 32)
> formulieren kann.

Ja, da habe ich Deine Intention ein wenig missverstanden. Nein, ein sehr 
löblicher Ansatz, der eine der Hauptschwächen von (s)scanf und Konsorten 
verdeutlicht.

> (anscheinend Standard-)

Tja, und da liegt der sprichwörtliche Hase im Pfeffer. Zwar gibt es eine 
rege Gemeinde von Standard-Entwicklern, die den Standard 
weiterentwickeln, aber es gibt eine noch viel größere Anzahl von 
installierten und benutzten Entwicklungssystemen, die nach wie vor C89 
("ANSI-C") implementieren.

Auch das --als C++-Compiler unbestritten exzellente-- MS Visual C++ 2005 
kennt keine "inttypes.h". Gut, "Juliettas" Zielsystem scheint kein 
Windows-System zu sein, aber sie hat in ihrem Drang, einen mit 
Informationen zu überschwemmen, weder das Zielsystem noch den 
verwendeten Compiler genannt.
#797633
Lesenswert?

Rufus t. Firefly wrote:

>> (anscheinend Standard-)
>
> Tja, und da liegt der sprichwörtliche Hase im Pfeffer. Zwar gibt es eine
> rege Gemeinde von Standard-Entwicklern, die den Standard
> weiterentwickeln, aber es gibt eine noch viel größere Anzahl von
> installierten und benutzten Entwicklungssystemen, die nach wie vor C89
> ("ANSI-C") implementieren.

Wie wahr, wie wahr.

>
> Auch das --als C++-Compiler unbestritten exzellente-- MS Visual C++ 2005
> kennt keine "inttypes.h". Gut, "Juliettas" Zielsystem scheint kein
> Windows-System zu sein, aber sie hat in ihrem Drang, einen mit
> Informationen zu überschwemmen, weder das Zielsystem noch den
> verwendeten Compiler genannt.

Ja, so sind sie, die Weiber: geschwätzig!

(War nicht ernst gemeint!)
#807142
Lesenswert?

Rufus t. Firefly wrote:
>>  Mit fscanf kann so nicht gearbeitet werden, denn es erwartet bei %x
>>  Format einen Speicherplatz für ein int als Argument.
>
> Das ist es ja, was ich bereits mehrfach angesprochen habe, und was auch
> Karl Heinz meinte, wenn auch er irrigerweise von einem 16-Bit-System
> ausgegangen war.
>
>
> Wenn aus welchen Gründen auch immer "Julietta" nicht in der Lage sein
> sollte, 16-Bit-Werte via (s)scanf aus einer Textdatei einzulesen, dann
> ließe sich natürlich auch eine andere Vorgehensweise wählen:
>
>
1
> #include<stdio.h>
2
> 
3
> typedef short int int16;
4
> typedef long int int32;
5
> int main()
6
> {
7
>   FILE *data_fp;
8
>   int32 wert32;
9
>   int16 datain16[100];
10
>   int16 *ptr16;
11
>   data_fp = fopen(".../datain.dat","r");
12
>   int i;
13
> 
14
>   if (data_fp != NULL)
15
>   {
16
>     for (i = 0; i < 7; i++)
17
>     {
18
>       fscanf(data_fp, "%8x", &wert32);
19
>       datain16[i * 2] = (int16) ((wert32 >> 16) & 0xffff);
20
>       datain16[i * 2 + 1] = (int16) (wert32 & 0xffff);
21
>     }
22
> 
23
>   for(i = 0; i < 4; i++)
24
>   {
25
>     printf("datain16[%d]:%x\t", i, (int) datain16[i]);
26
>   }
27
>   return 0;
28
> }
29
>
>
> Das ist natürlich 'ne heikle Angelegenheit, bei der die endianness der
> Zielmaschine berücksichtigt werden muss. Angegeben ist die Intel-Sicht
> der Welt.

da bin ich nochmals mit diesem Problem :)
ich habe den obigen Code benutzt. Aber ich habe noch ein Problem, wenn 
ich einen Wert von 0xffffffff oder 0x30aabbcc habe, dann sehen meine 
datain16 wie folgt aus:

datain16[0]: ffffffff
datain16[2]: ffffffff
datain16[3]: 30aa
datain16[4]: ffffbbcc

Wie kann ich dieses Problem verhindern?
#807559
Lesenswert?

> datain16[4]: ffffbbcc

Die ffff ganz links entstehen 'in der Ausgabe', weil das
höchstwertige Bit im int16 gesetzt ist. Dadurch behandelt
das System das ganze als negative Zahl und beim Aufblasen
auf einen normalen int wird ffff ergänzt.

-> wenn du mit Bytewerten oder Wordwerten hantierst, dann immer
auf unsigned achten! Ansonsten entwickelt das most signifikant
Bit ein Eigenleben welches einem den Tag versauen kann.

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