In C++ geht das, aber irgendwie will C (WinARM) es nicht akzeptieren.
Was ich will ist eigentlich folgendes.
Ich gehe mal davon aus, dass bei 8-Bit-Mikrocontrollern das Addressieren
über Pointer von extra Befehlen begleitet wird. Ich stelle mir vor
(keine Ahnung ob es stimmt), dass wenn ich ein struct an eine feste
Addresse lege, der Compiler die einzelnen Felder direkt ansprechen kann,
da die Addresse des Objekts ja fix ist. Also keine Pointeraddressierung.
Nun möchte ich in mehreren Funktion, die ich aufrufe, auf einen
Speicherbereich zugreifen, der an einer festen Addresse liegt.
Allerdings wird der Bereich in jeder Funktion unterschiedlich genutzt,
so dass ich gerne für jede Funktion ein struct deklarieren würde, der
die Struktur beschreibt.
Meine Frage ist nun, wie sage ich dem C-Compiler, dass die Variable ff
die Struktur structure hat und fix an Addresse &f im Speicher liegt, so
dass der Compiler weiß, dass er nicht mit Pointern herumhantieren muss?
Genau, und genau das wollte ich vermeiden, da ja bei einem Pointer
prinzipel das Objekt überall im Speicher liegen könnte. Da mein Objekt
jedoch an einer festen Stelle liegt, suche ich nach einer Möglichkeit,
die den Compiler hoffenlich dazu bringt, nicht über Pointerarithmetik
auf den Speicher zuzugreifen, sondern einfach direkt.
Auch wenn ich derzeit auf einem AVR schreibe, ist es zumindes beim PIC
so, dass der direkte Zugriff nur einen Zyklus benötigt, während die
Verwendung von Pointern in etlichen Maschinenbefehlen endet.
Hier noch mal ein paar Deteils:
62: ts *s=message+1;
+00000362: E08D LDI R24,0x0D Load immediate
+00000363: E091 LDI R25,0x01 Load immediate
+00000364: 839D STD Y+5,R25 Store indirect with
displacement
+00000365: 838C STD Y+4,R24 Store indirect with
displacement
64: s->value=3;
+00000366: 81EC LDD R30,Y+4 Load indirect with
displacement
+00000367: 81FD LDD R31,Y+5 Load indirect with
displacement
+00000368: E083 LDI R24,0x03 Load immediate
+00000369: E090 LDI R25,0x00 Load immediate
+0000036A: 8391 STD Z+1,R25 Store indirect with
displacement
+0000036B: 8380 STD Z+0,R24 Store indirect with
displacement
65: s->string[3]='a';
+0000036C: 81EC LDD R30,Y+4 Load indirect with
displacement
+0000036D: 81FD LDD R31,Y+5 Load indirect with
displacement
+0000036E: E681 LDI R24,0x61 Load immediate
+0000036F: 8385 STD Z+5,R24 Store indirect with
displacement
67: xx.value=7;
+00000370: E087 LDI R24,0x07 Load immediate
+00000371: E090 LDI R25,0x00 Load immediate
+00000372: 93900101 STS 0x0101,R25 Store direct to data
space
+00000374: 93800100 STS 0x0100,R24 Store direct to data
space
68: xx.string[3]='a';
+00000376: E681 LDI R24,0x61 Load immediate
+00000377: 93800105 STS 0x0105,R24 Store direct to data
space
Sowohl s als auch xx sind vom type ts. Aber s ist ein pointer. Man
sieht, dass die Pointervariante deutlich mehr Befehle braucht, obwohl
'message' fix an einer Konstanten Addresse liegt.
Eine C++-Refernz ist intern nichts anderes als ein Pointer. Der
Unterschied liegt in der Syntax (sie braucht für den Zugriff nicht
dereferenziert zu werden) und in der fehlenden Möglichkeit, ihr einen
Adresswert zuzuweisen (nur eine einmalige Initialisierung ist
möglich).
Daraus ergibt sich, dass sich der für Datenzugriffe über Pointer oder
Referenzen erzeugte Code nicht oder höchstens unwesentlich
unterscheidet.
Nur wenn der Compiler erkennen kann, welche Adresse sich hinter einer
Referenz verbirgt, wird er einen direkten Zugriff auf die Variable
generieren. Das ist bei der Verwendung eines Pointers aber das
Gleiche: Auch dort wird er auf die Derefenzierung verzichten, wenn ihm
klar ist, dass der Pointer nur einen ganz bestimmten Wert annehmen
kann. Ob er diese Optimierung tatsächlich durchführt, kannst du dem
erzeugten Assemblercode entnehmen.
Aber warum möchtest du überhaupt über eine Referenz oder einen Pointer
auf f zugreifen, wenn dieser Pointer sowieso konstant ist? Greift du
direkt auf f zu, wird der Compiler immer den gewünschten optimalen
Code erzeugen.
Zu deinem geposteten Code: Du hast beim Compilieren die Optimierung
nicht eingeschaltet (-O1 oder -O2). Speziell in diesem Beispiel kann
der Compiler nämlich tatsächlich die Dereferenzierung über das
Z-Register wegoptimieren, womit dein Problem vielleicht schon gelöst
ist.
Bernd M. wrote:
> Ich würde gerne folgendes machen:>
1
>structuref;
2
>structure&ff=f;
3
>
>> In C++ geht das, aber irgendwie will C (WinARM) es nicht akzeptieren.
Logisch. C ist nun mal eine andere Sprache als C++.
> Nun möchte ich in mehreren Funktion, die ich aufrufe, auf einen> Speicherbereich zugreifen, der an einer festen Addresse liegt.> Allerdings wird der Bereich in jeder Funktion unterschiedlich genutzt,> so dass ich gerne für jede Funktion ein struct deklarieren würde, der> die Struktur beschreibt.> Meine Frage ist nun, wie sage ich dem C-Compiler, dass die Variable ff> die Struktur structure hat und fix an Addresse &f im Speicher liegt, so> dass der Compiler weiß, dass er nicht mit Pointern herumhantieren muss?
Fasse die einzelnen Strukturbeschreibungen in eine union zusammen.
1
structMyA
2
{intMem1;};
3
4
structMyB
5
{doubleMem2;};
6
7
structMyC
8
{charMem3;};
9
10
union{
11
structMyAa;
12
structMyBb;
13
structMyCc;
14
}Overlay;
15
16
Overlay.a.Mem1=5;
17
Overlay.b.Mem2=8.0;
18
Overlay.c.Mem3='a';
Kein Grund zu schmutzigen Tricks zu greifen. Das lässt sich mit
C-Hausmitteln erreichen.
@yalu:
Stimmt, da das Debugging mit optimiertem Code nicht so richtig wollte,
habe ich die Optimierung ausgeschaltet. Mit Optimierung macht er
tatsächlich was ich mir vorstelle. Na ja, mit Pointern kann man auch
Leben, wenn man mal davon absieht, dass man da immer 2 Zeichen eintippen
muss :-)
@Karl heinz Buchegger:
Das mit der union habe ich auch schon probiert. Das Problem ist nur,
dass der Speicher an sich in einer Datei deklariert wird, die von einem
Code Generator stammt.
Die structs sollen nur dazu dienen, dass man als Benutzer dieses
generierten Codes nicht mühselig die Datenstruktur wieder
zusammenstricken muss. Statt dessen einfach ein struct definieren und
dann so tun, als ob der Datenblock dieser struct wäre.
Grüße,
Bernd
Bernd M. wrote:
> @yalu:> Stimmt, da das Debugging mit optimiertem Code nicht so richtig wollte,> habe ich die Optimierung ausgeschaltet. Mit Optimierung macht er> tatsächlich was ich mir vorstelle. Na ja, mit Pointern kann man auch> Leben, wenn man mal davon absieht, dass man da immer 2 Zeichen eintippen> muss :-)
Es soll da IDEs geben die einem sogar das abnehmen. '.' wird, wenn es
sich beim rechten Typ um einen Pointer handelt automatisch zu einem ->
erweitert. Sehr praktisch das.
Matthias