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
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.
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.
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
//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
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);
>> 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.
:(
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?
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.
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
return0;
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.
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).
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
>#defineSCNx16"x"
2
>#defineSCNx32"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.
> 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
typedefshortintint16;
4
typedeflongintint32;
5
intmain()
6
{
7
FILE*data_fp;
8
int32wert32;
9
int16datain16[100];
10
int16*ptr16;
11
data_fp=fopen(".../datain.dat","r");
12
inti;
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
return0;
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.
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.
> 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.
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!)
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
>typedefshortintint16;
4
>typedeflongintint32;
5
>intmain()
6
>{
7
>FILE*data_fp;
8
>int32wert32;
9
>int16datain16[100];
10
>int16*ptr16;
11
>data_fp=fopen(".../datain.dat","r");
12
>inti;
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
>return0;
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?
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
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]);
}
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.
> 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.