Forum: PC-Programmierung Arbeit mit 16 bit in 32 bit system in C


von Julietta O. (eiskalt)


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

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wie groß ist auf Deinem 32-Bit-System

  sizeof (short)?

In C ist

sizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long)

nur die genaue Verteilung kann von Zielsystem zu Zielsystem differieren.

von Julietta O. (eiskalt)


Lesenswert?

sizeof(int) = 4 byte

von yalu (Gast)


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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> sizeof(int) = 4 byte

Und? Was habe ich geschrieben?

  sizeof (short)!

von Julietta O. (eiskalt)


Lesenswert?

Rufus t. Firefly wrote:
>> sizeof(int) = 4 byte
>
> Und? Was habe ich geschrieben?
>
>   sizeof (short)!

klar sizeof(short) = 2

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Na also!

von Julietta O. (eiskalt)


Lesenswert?

Ja. Das weiß ich. Aber wenn ich eine Pointer 16 bit benutzen dann zeigt 
diese Pinter nur auf 1 Adresse 32 bit. Also wenn ich diese pointer 
inkrementiere
z.B pointer ++

dann springt er zum MSB von 32 Bit und nicht weiter. Er kann nicht zum 
2. 32bit springen

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Was lässt Dich dies annehmen?

von Julietta O. (eiskalt)


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

von Rufus Τ. F. (rufus) Benutzerseite


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);

von Julietta O. (eiskalt)


Lesenswert?

>Du bist Dir sicher, daß diese Codezeile funktioniert?
>
>   fscanf(data_fp,"%8x",&datain32[i]);

Ja das funktioniert.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Wenn Du es so schreibst, ja. Das aber hattest Du in Deinem 
ursprünglichen Posting nicht getan.
1
&datain32[i]
 ist dasselbe wie
1
datain32 + i

Hast Du Dir auch den zweiten Teil meines Beitrags von gestern angesehen?

von Julietta O. (eiskalt)


Lesenswert?

>
1
&datain32[i]
 ist dasselbe wie
1
datain32 + i
>
> Hast Du Dir auch den zweiten Teil meines Beitrags von gestern angesehen?

ja. Ich habe dasa auch schon probiert und bekomme die gleiche 
Ergebnisse. Ich meine die Ergebnisse von datain16, was ich vorher auch 
schon gehabt haben.

:(

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Julietta O. (eiskalt)


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

von Karl H. (kbuchegg)


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
  }

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Draco (Gast)


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).

von Draco (Gast)


Lesenswert?

>16 Bit haben im Programm 4 Bytes und 32 Bit haben 8 Bytes?
OK, das ist wohl Quatsch (-;

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


Lesenswert?

Draco wrote:

>  Der Filepointer wird nicht zurückgespult.

Ich geh mal davon aus, dass das gepostete ein Konglomerat
aus 2 getrennten Programmen ist.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Karl H. (kbuchegg)


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.

von Rufus Τ. F. (rufus) Benutzerseite


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.

von Karl H. (kbuchegg)


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!)

von Julietta O. (eiskalt)


Lesenswert?

Danke für die Antworte :)

von Julietta O. (eiskalt)


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?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du verwendest hartnäckig falsche Formatspezifizierer, diesmal für 
printf.

%x spezifiziert einen (in Deinem Fall) 32 Bit breiten int, Du willst 
aber einen (in Deinem Fall) 16 Bit breiten short verwenden.

Verwende mal %hx

von Julietta O. (eiskalt)


Lesenswert?

Wenn ich %hx benutze, dann bekomme ich ein "Segmentation fault"

#define SCNx16 "hx"

for(i = 0; i < 4; i++)
   {
     printf("datain16[%d]:%hx\t", i, (int) datain16[i]);
   }

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Ja, sicher. Du machst ja auch noch zusätzlich einen Typecast nach 
int.

Lass den weg.

von Julietta O. (eiskalt)


Lesenswert?

Es geht immer noch nicht auch wenn ich "int" weg mache

von Karl H. (kbuchegg)


Lesenswert?

Rufus t. Firefly wrote:
> Ja, sicher. Du machst ja auch noch zusätzlich einen Typecast nach
> int.
>
> Lass den weg.

Das sollte keine Rolle spielen. Durch die Integer
Promotion wird auch ein char oder short als int übergeben.

von Karl H. (kbuchegg)


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.

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.