Darf man die Adresse einer Structure nicht erfragen? "&struct->dword"

Gast #4198167
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
#4198194
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.
#4198218
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
Moderator Persönliche Seite #4198280
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.
Gast #4198285
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)
Gast #4198286
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.
Gast #4198301
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.
Gast #4198314
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));
#4198321
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.
Gast #4198322
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.
#4198335
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!!!!!!!!!!
Gast #4198348
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
Gast #4198353
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 ;-)
Gast #4198359
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.

;-)
#4198377
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
}
Gast #4198393
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.
#4198415
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
Gast #4198577
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
#4198737
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.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.