Forum: Compiler & IDEs EProm im AVRGCC Tutorial


von Frischling (Gast)


Lesenswert?

1
uint8_t  myByteBuffer[3];
2
uint16_t myWordBuffer[4];
3
 
4
void eeprom_block_example (void)
5
{
6
    /* Datenblock aus EEPROM lesen  */
7
 
8
    /* liest 3 Bytes ab der von eeFooByteArray1 definierten EEPROM-Adresse
9
       in das RAM-Array myByteBuffer */
10
    eeprom_read_block (myByteBuffer, eeFooByteArray1, 3);
11
 
12
    /* dito mit etwas Absicherung betr. der Länge */
13
    eeprom_read_block (myByteBuffer, eeFooByteArray1, sizeof(myByteBuffer));
14
 
15
    /* und nun mit 16-Bit Array */
16
    eeprom_read_block (myWordBuffer, eeFooWordArray1, sizeof(myWordBuffer));
17
 
18
    /* Datenblock in EEPROM schreiben */
19
    eeprom_write_block (myByteBuffer, eeFooByteArray1, sizeof(myByteBuffer));
20
    eeprom_write_block (myWordBuffer, eeFooWordArray1, sizeof(myWordBuffer));
21
}

Obiges Beispiel findet man im Tutorial zum AVRGCC.
Leider verstehe ich das nicht.

MyByteBuffer und MyWordBuffer sind normale Variablen.
Aber die Blockoperationen auf das EEPROM erwarten doch einen Pointer !?

Da müsste doch jeweils ein & vor den Variablen stehen, oder ??

von Krapao (Gast)


Lesenswert?

Es sind Felder (Arrays). Und da ist MyByteBuffer gleichbedeutend mit 
&MyByteBuffer[0]. Beides ist die Adresse des ersten Elementes im Feld.

von Frischling (Gast)


Lesenswert?

Also ist hier die "interne Representation" des Array der Knackpunkt.

Der Compiler macht dort Pointerarithmetik und verheimlicht es mir ??

Gegenprobe :

Bei jeder anderen Variable, Struct etc müsste ich den referenzierungs 
operator benutzen ?

von Krapao (Gast)


Lesenswert?

Nö der verheimlicht nix. Das ist ein dokumentiertes Verhalten der C 
Sprache.

Genau kannst du das im ANSI C Standard 
(http://www.go4expert.com/forums/showthread.php?t=13) nachlesen bzw. ist 
das auch ein Abschnitt in jedem gängigen C Lehrbuch. In der FAQ steht es 
auch (http://c-faq.com/aryptr/aryptrequiv.html).

von Frischling (Gast)


Lesenswert?

Sozusagen Syntaktischer Zucker.

MyBytePuffer ist also ein Pointer auf das erste Element.

Die eckigen Klammern [] sind dann quasi der Dereferenzierungsoperator (* 
mit Elementinkrementierfunktion).

Das erklärt dann auch warum wir unsere Elemente von null aus abzählen.
(glaube gerade ist der Grosschen gefallen)

Vielen Dank !

von Karl H. (kbuchegg)


Lesenswert?

Frischling schrieb:
> Sozusagen Syntaktischer Zucker.
>
> MyBytePuffer ist also ein Pointer auf das erste Element.

Ich denke du meinst das richtige. Aber Vorsicht: Die Sprechweise
"Array xyz IST ein Pointer..."
stimmt so nicht.
Ein Array ist ein Array und ein Pointer ist ein Pointer.
Aber in bestimmten Situationen fungiert der Name eines Arrays, wenn er 
alleine steht, wie ein Pointer auf den Beginn der Daten.

Array selber IST kein Pointer, es degeneriert nur zur Startadresse des 
ersten Elements.

>
> Die eckigen Klammern [] sind dann quasi der Dereferenzierungsoperator (*
> mit Elementinkrementierfunktion).

Genau

   a[i]  <==>  *( a + i )

Das ist in C so definiert und das erste, was der COmpiler mit deiner 
Arrayindizierung mittels[] macht: Umwandeln in eine Pointer-Schreibweise 
und die dann bearbeiten.

von Frischling (Gast)


Lesenswert?

Irgendwie ist die Aussage über den Dereferenzierungsoperator schon 
verinnerlicht.
Immerhin erklärt das die ganze Zauberei drum herum.


Ich verkompliziere noch mal.
Interessant wäre was der Compiler daraus macht :
1
uint8_t 
2
        MeinArray[10] {1,2,3,4,5,6,7,8,9,0},
3
        *ptr1,
4
        *ptr2;
5
6
ptr1 = &MeinArray [0];
7
8
ptr2 = &MainArray;
9
10
if (*ptr2 == ptr1) cout << "Ich bin Wahr";
11
12
if (*ptr1 == 1) cout << "Ich bin Wahr";
13
if (**ptr2 == 1) cout <<"Ich bin Wahr";

ptr1 hatten wir schon, es zeigt auf das erste Element.

ptr2 müsste nach obigem auf den Zeiger des Zeigers der auf das erste 
Element zeigt zeigen.

Für die EEPROM Routine heisst das es wäre mit meinem vermissten 
Referenzierungsoperator nur ein Byte in das EEProm geschrieben worden, 
die Adresse des Pointers.
(bei Verwendung von sizeof)

Sehr schön das ganze, was ich für einen Fehler gehalten habe ist einfach 
nur schönes C...

von Karl H. (kbuchegg)


Lesenswert?

Frischling schrieb:
> Irgendwie ist die Aussage über den Dereferenzierungsoperator schon
> verinnerlicht.
> Immerhin erklärt das die ganze Zauberei drum herum.

Nicht nur das. Es erklärt auch warum manche Dinge in der 
Pointerarithmetik so sind, wie sie sind.

> Interessant wäre was der Compiler daraus macht :

> ptr2 = &MainArray;

Streng genommen ist das ein Syntaxfehler. Die meisten Compiler 
ignorieren den aber, weil es nur eine mögliche Interpretation gibt.

> if (*ptr2 == ptr1) cout << "Ich bin Wahr";

Das gibt auf einem zeitgemässen Compiler eine Warnung:
makes Pointer from Integer without a cast.

> if (*ptr1 == 1) cout << "Ich bin Wahr";

ist ok

> if (**ptr2 == 1) cout <<"Ich bin Wahr";

ist ein Syntaxfehler

> ptr2 müsste nach obigem auf den Zeiger des Zeigers der auf das erste
> Element zeigt zeigen.

Nö.

   uint8_t *ptr2;

ist ein einfacher Pointer.

> ptr2 müsste nach obigem auf den Zeiger des Zeigers der#
> auf das erste Element zeigt zeigen.

Genau das meinte ich mit: Sei vorsichtig in deiner Sprechweise.

Der Zeiger auf das erste Element existiert nicht als adressierbares 
Objekt. Damit kannst du auch keinen Zeiger darauf bilden. Ein Array ist 
ein Array und kein Pointer.

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.