Forum: Mikrocontroller und Digitale Elektronik Darf man die Adresse einer Structure nicht erfragen? "&struct->dword"


von Simon (Gast)


Lesenswert?

1
typedef struct _buffer_status { 
2
    uint32_t cnt;
3
    uint16_t chunksize;
4
} BUFFER_STATUS;
5
6
7
static BUFFER_STATUS status_buffer;
8
9
10
11
void fb_buffer_write_stop(BUFFER_STATUS *bf) {
12
    uint16_t chksum;
13
    uint32_t tmp_cnt;
14
15
    tmp_cnt = 0x1122AAEE;
16
   
17
// Geht bestens:
18
    SSTFlash_Write(bf->addr_tmp,(uint8_t *)&tmp_cnt,sizeof(tmp_cnt));
19
    chksum_add((uint8_t *)&tmp_cnt, sizeof(tmp_cnt));
20
    bf->addr_tmp += sizeof(tmp_cnt);
21
22
// geht nicht:
23
    SSTFlash_Write(bf->addr_tmp,(uint8_t *)&bf->cnt,sizeof(bf->cnt));
24
    chksum_add((uint8_t *)&bf->cnt, sizeof(bf->cnt));
25
    bf->addr_tmp += sizeof(bf->cnt);

Frage:

Wie erfragt man mit einem & die Adresse  von einer structure Richtig?

Ist das so nicht ok?
(uint8_t *)&bf->cnt

von Stefan F. (Gast)


Lesenswert?

Du ermittelst hier nicht die Adresse der Struktur, sondern die Adresse 
eines Feldes in der Struktur.

von P. M. (o-o)


Lesenswert?

Simon schrieb:
> // geht nicht:

"Geht nicht" ist im allgemeinen keine gute Beschreibung für ein Problem. 
Auch ein erfahrener Programmierer sieht mitunter nicht sofort das 
Problem in einem Programm, das "nicht geht". Deshalb sollte man 
mindestens anfügen, welche Fehler der Compiler ausspuckt oder inwiefern 
das Programm nicht/falsch funktioniert. Auch deshalb, weil je nach 
Sprachversion und Plattform nicht die gleichen Spielregeln gelten.

von Marc S. (marc_s86)


Lesenswert?

probier mal (uint8_t *)&(bf->cnt)

von (prx) A. K. (prx)


Lesenswert?

Ändert nichts. "->" bindet sowieso schon stärker als "&".

von "c-hater"-hater (Gast)


Lesenswert?

Willst du die Adresse des structs oder die eines Members?
Falle ersteres:
1
address = &bf;

von Richard T. (richi1901)


Lesenswert?

Also ich kann auch mal nur raten, aber von dem hier gezeigten Code 
stimmt das definierte Struct nicht mit dem Parameter überein wo 
aufgerufen werden.

Als zweitens frage ich mich warum du cnt als 16 bit definierst aber dann 
doch wieder auf einen 8 bit wert(bzw. Pointer) castest.

Noch interessanter wäre es wenn man mehr vom Code sehen würde, oder gib 
uns die Prototypen von den aufzurufenden Funktionen.

Und wie schon erwähnt welchen Fehler spukt der Compiler aus. Oder lässt 
sich es kompilieren ? Wenn ja wo durch merkst du das es nicht 
funktioniert ?

Viele Grüße
Richi

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon schrieb:
> // Geht bestens:

Glaub' ich nicht.

von Simon (Gast)


Lesenswert?

Jörg W. schrieb:
> Glaub' ich nicht.

Tuts, wirklich bestens, ich benötige die adresse vom member eines 
structs

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Simon schrieb:
> Tuts, wirklich bestens

Ganz gewiss nicht.  bf->addr_tmp gibt es nämlich nicht.

Wenn du hier irgendeine ernsthafte Hilfe wünschst, dann fake bitte
nicht irgendwelchen Code, von dem du glaubst, dass er zu dem, mit
dem du ein Problem hast, äquivalent wäre.  Schneide den problematischen
Code soweit zusammen, dass das Problem möglichst kurz und knapp übrig
bleibt und poste dann den Code, aber bitte zusammen mit der konkreten
Fehlermeldung.

von Simon (Gast)


Lesenswert?

Ah moment da waren mehr Fragen.

er liest schlichtweg das falsche aus, als ob er von einer falsche 
adresse liest. das sizeof funzt jedoch auch bestens.

compilen geht ohne jeglicher warnung.

Der Prototyp für chksum ist

void chksum_add (const BYTE* buffer, WORD count)

von Klaus (Gast)


Lesenswert?

Simon schrieb:
> Jörg W. schrieb:
>> Glaub' ich nicht.
>
> Tuts, wirklich bestens, ich benötige die adresse vom member eines
> structs

Also, dass man mal was übersieht - und auch mal hartnäckig am Problem 
vorbei schaut -, dass passiert den Besten. Mir nicht, aber Klaus. :-)

Aber glaub mir, wenn Jörg Wunsch und noch ein paar das sagen, dann ist 
es höchste Zeit mal "ganz scharf" hinzu schauen. Wenn man dann noch 
nichts sieht, mal ein paar Stunden schlafen oder einen schönen 
Spaziergang machen. Auf jeden Fall erst aufhören, wenn der Code ohne 
Fehlermeldung compiliert. Das tut er nämlich nicht.

Es ist schlicht unmöglich, dass der gezeigte Code jemals funktioniert 
hat.

Du hast hier gleich mehrere Ungeschicklichkeiten begangen, die sich nun 
leider zu einem Kuddel-Muddel gegen Dich vereinigen.

1. (Vermutlich) den Code nicht mit Copy&Paste eingefügt bzw. 
nachträglich so bearbeitet, dass er nicht mehr kompilierbar ist.

2. Fehler nicht beschrieben. Ein ganz böses Versäumnis. Denn so kann dir 
niemand helfen Dir zu helfen.

3. Erkennbar einige grundlegende Mängel im Verständnis von C. Das allein 
wäre nicht weiter schlimm, wenn es das einzige Problem wäre.

Versuche die Punkte 1. bis 3. in Deiner Fragestellung zu korrigieren. Es 
musst nicht perfekt sein, aber das Bemühen erkennbar.

von Klaus (Gast)


Lesenswert?

Simon schrieb:
> compilen geht ohne jeglicher warnung.

Das mag unter Umständen so sein. Aber dafür kriegst Du einen Haufen 
Fehlermeldungen.

Ich möchte Dich ernstlich davor warnen, auf die bisherige Art in diesem 
Thread fortzufahren. Andernfalls wird Dir nicht geholfen oder Du wirst 
möglicherweise mit zunehmender Härte kritisiert.

von Richard T. (richi1901)


Lesenswert?

Simon schrieb:
> er liest schlichtweg das falsche aus, als ob er von einer falsche
> adresse liest. das sizeof funzt jedoch auch bestens.

Okay wäre noch schön zu wissen was du erwatest und was du zurück 
bekommst.

von Simon (Gast)


Lesenswert?

Bleiben wir mal nur bei einer Zeile code.

Dieser code funktioniert tadellos, er compiled und
das errechnete Ergebnis stimmt.

Das gilt sowohl für das sizeof() als auch die übergebene Adresse
von &tmp_cnt
1
    uint32_t tmp_cnt;
2
    tmp_cnt = 0x1122AAEE;
3
    chksum_add((uint8_t *)&tmp_cnt, sizeof(tmp_cnt));


Meine Frage ist hier einfach warum das bei einem struct nicht mehr der 
fall ist.
1
    uint32_t tmp_cnt;
2
    bf->cnt = 0x1122AAEE; // zuweisung funktioniert
3
    chksum_add((uint8_t *)&bf->cnt, sizeof(bf->cnt));

von (prx) A. K. (prx)


Lesenswert?

Es ist bekanntlich leichter, den verlorenen Schlüssel unter der 
Strassenlaterne zu suchen, als in jener dunklen Ecke, in der man ihn 
verlor. Aber finden wird man ihn da nicht.

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

> Meine Frage ist hier einfach warum das bei einem struct nicht mehr der
> fall ist.

Keine Ahnung.
Vielleicht zeigt dein Pointer bf in den Wald?

Wie schon gesagt: kompletten, compilierbaren Code, der das betreffende 
Verhalten zeigt.

Es ist ein Mythos, dass man alle Fehler an einer einzigen Zeile Code 
festmachen kann. Oft steckt der Fehler ganz woanders, als du ihn 
vermutest. Was du bist jetzt hast, ist die Zeile an der sich die 
Symptome bemerkbar machen. Aber das Problem kann auch ganz woanders 
sitzen.

von Klaus (Gast)


Lesenswert?

Simon schrieb:
> Bleiben wir mal nur bei einer Zeile code.

Das ist noch so eine Ungeschicklichkeit. Nun gut. Ich habe Dich gewarnt. 
Mehr kann man nicht tun.

WIR sind diejenigen die Du fragst und WIR bestimmen wie und wo es 
langgeht.

Wenn Du darauf bestehst, uns die Richtung vorzugeben, dann löse das 
Problem auch alleine. Wir wissen selbst wie man Fehler sucht und bei 
Fragen vorgeht.
Dazu brauchen wir keine Belehrung von Dir. Es ist gerade umgekehrt.

von Richard T. (richi1901)


Lesenswert?

Naja ich geb jetzt mal auf hier für Hirngespinste hab ich keine Zeit 
bzw. mag keine Zeit investiern. Entwerder Code oder keine Hilfe mehr, es 
wird ja hier nicht mal auf ernst gemeinte fragen geantwortet.

Jeder der hier versucht gutes zu leisten soll es lassen da, der TE nicht 
wirklich kooperiert!!!!!!!!!!

von Simon (Gast)


Lesenswert?

Karl H. schrieb:
> Keine Ahnung.
> Vielleicht zeigt dein Pointer bf in den Wald?

Ich hab den code mal durch gesteppt, ne ansich auch nicht, merkwürdig.

Inzwischen glaube ich das (uint8_t *)&bf->cnt einfach korrekt ist

von Karl H. (kbuchegg)


Lesenswert?

Simon schrieb:

> Inzwischen glaube ich das (uint8_t *)&bf->cnt einfach korrekt ist

Ist es auch.

Wie gesagt: Symptom - Ursache.

Du siehst das Symptom. Die Ursache steckt woanders.

von Simon (Gast)


Lesenswert?

Klaus, relax,

mir ist schon klar das mir hier keiner Helfen kann für code den ich hier 
nicht poste, mir ging es einfach nur darum ob das casten sowie die frage 
nach der adresse so korrekt ist, ich war mir einfach unsicher

von .. (Gast)


Lesenswert?

Simon schrieb:
>
1
> 
2
> 
3
> void fb_buffer_write_stop(BUFFER_STATUS *bf) { // << wo endet das?
4
>     uint16_t chksum;
5
>     uint32_t tmp_cnt;
6
> ....
7
> // Geht bestens:
8
>     SSTFlash_Write(bf->addr_tmp,(uint8_t *)&tmp_cnt,sizeof(tmp_cnt));
9
> ....
10
> // geht nicht:
11
>     SSTFlash_Write(bf->addr_tmp,(uint8_t *)&bf->cnt,sizeof(bf->cnt));
12
>
13
> // das kann so nicht funktionieren was du postest - sorry!
14
> // und die Glaskugel gibt es noch nicht.
15
> // poste halt den Code komplett und was danach noch kommt.
16
>
17
>
>
"Bitte reduzieren Sie die Anzahl der Zitatzeilen"
Hab ich gemacht und jetzt ist es noch unübersichtlicher.
Aber wo endet dein Funktionskopf ;-)

von Klaus (Gast)


Lesenswert?

Simon schrieb:
> Klaus, relax,

Was lässt Dich annehmen, dass ich mich irgendwie aufrege? Das gewöhne 
ich mir gerade mit einigem Erfolg ab.

Helf' ich nicht Dir, dann dem Nächsten der geschickter fragt.

von .. (Gast)


Lesenswert?

@Simon

Setze 'bitte' erst mal deine Funktionsklammern richtig;
dann setz dich mit der Frage hin, warum der Compiler
da stehen bleibt wo er steht, wenn er noch stehen bleibt;
ich denke dass dein Contsruct gut aussieht, aber du vermasselst
es mit der Klammer.

;-)

von Simon (Gast)


Lesenswert?

Wat wie wo welche klammer?!?

von .. (Gast)


Lesenswert?

Simon schrieb:
> Wat wie wo welche klammer?!?

Mal mundart:
Du machst doch am Schluss der Zeile auf
1
void fb_buffer_write_stop(BUFFER_STATUS *bf) {

wo machst du in deinem Code wieder zu
1
}

von Daniel A. (daniel-a)


Lesenswert?

Karl H. schrieb:
> Du siehst das Symptom. Die Ursache steckt woanders

Dazu ein Beispiel:
1
#include <stdbool.h>
2
#include <stdio.h>
3
#include <string.h>
4
int main(){
5
  struct {
6
    char text[4];
7
    bool running;
8
  } datas;
9
  datas.running = true;
10
  while(datas.running) // <-- Symptom
11
    strcpy(datas.text,"test"); // <-- Uhrsache
12
  printf("%.4s Hahaha!\n",datas.text);
13
  return 0;
14
}

von C-lerner (Gast)


Lesenswert?

Simon schrieb:
> void chksum_add (const BYTE* buffer, WORD count)
Simon schrieb:
> chksum_add((uint8_t *)&tmp_cnt, sizeof(tmp_cnt));

Kleine Zwischenfrage an die C-Experten: Wäre hier ein void-Pointer nicht 
angebrachter?

von .. (Gast)


Lesenswert?

Simon schrieb:
> Bleiben wir mal nur bei einer Zeile code.
>
> Dieser code funktioniert tadellos, er compiled und
> das errechnete Ergebnis stimmt.
>
> Das gilt sowohl für das sizeof() als auch die übergebene Adresse
> von &tmp_cnt
>
>
1
>     uint32_t tmp_cnt;
2
>     tmp_cnt = 0x1122AAEE;
3
>     chksum_add((uint8_t *)&tmp_cnt, sizeof(tmp_cnt));
4
>

/*Glaskugel an:*/

Das wird daran liegen weil der Code im Funktionsrumpf steckt auf dessen 
Adressen er zugreift

>
>
> Meine Frage ist hier einfach warum das bei einem struct nicht mehr der
> fall ist.
>
>
1
>     uint32_t tmp_cnt;
2
>     bf->cnt = 0x1122AAEE; // zuweisung funktioniert
3
>     chksum_add((uint8_t *)&bf->cnt, sizeof(bf->cnt));
4
>

Weil das Struct irgendwo liegen kann, wir wissen es nicht wo es liegt,
auch die Glaskugel weiss es nicht, hast du dein struct in der header 
oder code file und hast du das eingebunden oder nicht, wir wissen es 
nicht.

Zumal der Code im Eröffnungspost auch nicht vollständig ist;
kein #include
kein #define
kein abgeschlossener Funktionsrumpf
aber umgeschriebener code aus einem Funktionsrumpf,
der funktioniert, auf ein Struct irgendwo im Projekt.
und der gleich zweimal im noch offenen Funktionsrumpf hängt.

mhm.
Wenn man dir sagt, "Super, der Struct Code müsste eigentlich gehen,
aber es läuft dann doch nicht bei dir, ist dir damit nicht geholfen
auf deine Frage geantwortet zu haben.

So wie der Code da steht, kann er nicht laufen

a) die Funktion "void fb_buffer_write_stop(BUFFER_STATUS *bf)"
hat einen Anfang aber kein Ende.

b) in der Funktion wird auf ein struct verwiesen, dass nicht includiert 
wurde

c) es ist ein Unterschied ob du jetzt den Code an und für sich bestätigt 
haben willst oder dir es um die Funktionalität geht. Denn, du siehst 
jetzt die Codezeile mit deinem struct Verweis, hast du alles dazu auch 
richtig includiert, zumindest fehlt die Endklammer schon mal von der 
Funktion "void fb_buffer_write_stop(BUFFER_STATUS *bf)".


> Du siehst das Symptom. Die Ursache steckt woanders

So ist es leider in deinem Fall.

von .. (Gast)


Lesenswert?


von .. (Gast)


Lesenswert?


von Vlad T. (vlad_tepesch)


Lesenswert?

Simon schrieb:
> Dieser code funktioniert tadellos, er compiled und
> das errechnete Ergebnis stimmt.

wie gesagt, dann ist es aber nicht der Code der da steht.

Simon schrieb:
> bf->addr_tmp += sizeof(bf->cnt);

abgesehen davon, dass es das Member nicht gibt, sieht das komisch aus.

Frage: Du weißt, was Alignement ist und was Padding Bytes sind?

Vielleicht steht an der Pufferadresse nur was anderes als du vermutest, 
weil der Puffer vorher anders Gefüllt wurde.

Beispiel:
1
typedef struct A { 
2
    uint8_t  a;
3
    uint16_t b;
4
    uint8_t  c;
5
    uint32_t d;
6
} A;

sieht mit großer wahrscheinlichkeit so aus:
1
typedef struct A { 
2
    uint8_t a;
3
    uint8_t _pad0;
4
    uint16_t b;
5
    uint8_t  c;
6
    uint8_t _pad1;
7
    uint8_t _pad2;
8
    uint8_t _pad3;
9
    uint32_t d;
10
} A;

wenn du jetzt einen Puffer bekommst, der eigentlich eine A* ist und du 
so ausließt
1
A a1;
2
A a2;
3
uint8_t* p = (uint8_t*)a1;
4
5
lese(p, (uint8_t*)&a2->a, sizeof(a2->a));
6
p +=sizeof(a2->a);
7
8
lese(p, (uint8_t*)&a2->b, sizeof(a2->b));
9
p +=sizeof(a2->b);
10
11
lese(p, (uint8_t*)&a2->c, sizeof(a2->c));
12
p +=sizeof(a2->c);
13
14
...
dann hast du am Ende Müll

von Simon (Gast)


Lesenswert?

Vlad Tepesch, vielen Dank für die Ausführliche Erklärung.

Ich erhöhe hier keinen pointer der dann natürlich je nach pading in 
einen falschen adressbereich gehen würde.

Allerdings habe ich da mal ne Frage, ich versuche es mal zu beschreiben.
1
    tmp_cnt = 0x1122AAEE;
2
    bf->cnt = tmp_cnt;
3
4
    ptr = (uint8_t*)&bf->cnt;  // 0xA00088E0
5
    eins = *ptr++;  // 0xA00088E1
6
    zwei = *ptr++;  // 0xA00088E2
7
    drei = *ptr++;  // 0xA00088E3
8
    vier = *ptr;
9
10
    ptr = (uint8_t*)&tmp_cnt; // 0xA001FED4
11
    eins = *ptr++; //0xA001FED5
12
    zwei = *ptr++; //0xA001FED6
13
    drei = *ptr++; //0xA001FED7
14
    vier = *ptr;

Der code ist getestet und funktioniert, das Ergebnis in den Variablen 
ist das selbe.

egal wie ich es also drehe der pointer zeigt auf die anfangsadresse und 
lässt sich genauso erhöhen wie eine normale Variable egal ob er 
bestandteil einer structure ist oder nicht

von Daniel A. (daniel-a)


Lesenswert?

Simon schrieb:
> Allerdings habe ich da mal ne Frage

Schade, dass wir die Frage nicht kennen. Du willst vermutlich die 
Funktionsweise von Pointerarithmetic, alignement und struct padding 
wissen.

Pointerarithmetik:
 1) Einem Pointer ist es egal, ob er in's nirvana oder sonstwohin zeigt. 
Das darf er, weil er nur eine Zahl ist. Es ist nur nicht erlaubt einen 
Pointer ins Nirvana zu dereferenzieren, da dies zu zugriffen auf 
ungültige oder unbekannte Speicherstellen führt.
 2) Pointer haben eine "einheit". Sie können nur um die grösse ihres 
darunterliegenden Datentyps erhöt oder verringert werden:
  ((uint32_t*)4)+1 entspricht &((uint32_t*)4)[1] entspricht (uint32_t*)8
  entspricht (uint32_t*)(((uint8_t*)4)+sizeof(uint32_t))

Alignement:
  Ein Pointer ist Aligned, wenn... ich formuliers lieber als c code:
    type* x; // ziel unbekannt
    bool aligned = ( ((uintptr_t)x) % sizeof(*x) ) == 0;
  Das dereferenzieren eines unaligned pointers ist erlaubt, aber 
undefiniert und sollte vermiden werden, ausser es ist dem Compiler 
bekannt z.B. bei packet struckts, die nicht teil des c standards sind.

Padding:
  1) Vor dem ersten Member einer union oder eines structs darf es kein 
Padding geben.
  2) Zwischen Arrayelementen darf es kein Padding geben.
  3) Zwischen struct Membern gleicher grösse darf es kein padding geben.
  4) Am Ende eines Structs und zwischen Structmembern unterschiedlicher 
grösse darf es padding geben.
  5) Die Padding bytes sind gültige Speicherbereiche die dereferenziert 
und überschrieben werden dürfen. z.B. mit memset.

Gut zu wissen:
  Mit alignof kann der offset eines Structmembers bestimmt werden. Das 
ermöglicht verrückte Präprozessor un c code tricks.

PS: Dein code hat ein Endiannes problem. Nutze Bitshifts oder hton.

von Simon (Gast)


Lesenswert?

Daniel A. schrieb:
> PS: Dein code hat ein Endiannes problem. Nutze Bitshifts oder hton.

Das war am ende auch das Problem.

Vielen Dank

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.