mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Zeiger - Knoten im Kopf?


Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Folgende Situation in C:

Es ist in einem fertigen Code ein array aus structs definiert.
Diesen Code möchte ich nicht ändern (zu viel aufwand)
const structa *structarray [] =
{
 &structelementa,
 &structelementb,
 ...,
};

Nun möchte ich dieses structarray an eine Function übergeben. Streng 
genommen  also den Zeiger.

Wie mache ich das?
So klappts ned.
void func (structa *uebergebenesstruct)
{
  irgendwastun();
}

func(&structarray); //Compiler meldet zwar keinen Fehler funktioniert aber nicht
Ich würde mich sehr über eine Erklärung freuen.
Vielen Dank

Autor: _ebtschi_ (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der Funktion musst du die Variable als 
uebergebenesstruct[i].irgendwas ansprechen. Also mit Stern davor. Keine 
Ahnung ob du das beachtet hast, wäre aber mein erster Tipp.

Ah, übersehen: das & gehört wohl weg, die Variable structarray ist 
bereits ein Pointer, und du willst ja nicht die Adresse von dem Pointer 
übergeben, nehm ich zumindest mal an ;-)

Autor: Name (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du eine Zeiger auf ein Struct übergeben hast kannst du nicht mehr 
über uebergebenesstruct.structelement zugreifen, sondern must 
dereferenzieren,
also uebergebenesstruct->structelement oder 
(*uebergebenesstruct).structelement vlt. liegts daran

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Es ist in einem fertigen Code ein array aus structs definiert.

Das ist ein Array aus Zeigern, nicht eines aus Structs.

> Nun möchte ich dieses structarray an eine Function übergeben. Streng
> genommen  also den Zeiger.

Kommt drauf an, was du mit "den Zeiger" meinst.

> Wie mache ich das?

Du mußt einen Zeiger auf das erste Element des Arrays übergeben. Dazu 
reicht es, den Namen des Arrays anzugeben. Daraus wird bei der 
Parameterübergabe automatisch ein Zeiger auf das erste Element.

> So klappts ned.
> void func (structa *uebergebenesstruct)

Du hast ja auch ein Array aus Zeigern auf structa. Ein Zeiger auf ein 
Element dieses Array wäre vom Typ Zeiger auf Zeiger auf structa, also 
müßte es heißen:
void func (structa **uebergebenesstruct)

> func(&structarray); //Compiler meldet zwar keinen Fehler funktioniert
> aber nicht

Dann sind die Warnungen zu niedrig eingestellt. Der Typ stimmt nicht. 
Beim Funktionsparameter hast du eine Zeigerebene zu wenig, beim Aufruf 
eine zuviel. Also einfach:
func(structarray);

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Vielen Dank erstmal.

Leider klappts noch nicht:

Der Compiler: pointer to different objects und zwar in der Zeile mit dem 
Funktionsaufruf:

func(structarray);

Tom G.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuche mal die Funktions-parameter-deklaration zu ändern:
void func (struct structa *uebergebenesstruct)
{
  irgendwastun();
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So muss es funktionieren

typedef struct structa_
{
  int a;
  int b;
} structa;

structa structelementa = { 0, 1 };
structa strcutelementb = { 2, 3 };

const structa *structarray [] =
{
 &structelementa,
 &structelementb,
};

void func (const structa **uebergebenesstruct)
{
  int i = uebergebenesstruct[0]->a;
  int j = uebergebenesstruct[0]->b;

  i = uebergebenesstruct[1]->a;
  j = uebergebenesstruct[1]->b;
}

int main()
{
  func( structarray );
}
Obwohl ich normalerweise nicht viel davon halte:
Man könnte die Funktionssignatur auch so anlegen, da wird
es eventuell etwas klarer:
void func (const structa *uebergebenesstruct[])
{
  ...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ebtschi wrote:
> In der Funktion musst du die Variable als
> uebergebenesstruct[i].irgendwas ansprechen.

Äh. Nein.

> Ah, übersehen: das & gehört wohl weg, die Variable structarray ist
> bereits ein Pointer,

Sei mit solchen Aussagen vorsichtig.
Du magst vielleicht das richtige meinen, aber so wie es da steht
ist das erst mal grundfalsch. Die Variable structarray ist kein
Pointer sondern ein Array. Und ein Array ist nun mal kein
Pointer.

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit dem Code von Karl heinz Buchegger erhalte ich keine Fehler.

Jedoch hab ich noch eine kleines Problem:

const structa *structarray [] =
{
 &structelementa,
 &structelementb,
 NULL
};


void func (const structa *uebergebenesstruct[])
{
 
 unsigned char count;
 
 while (&uebergebenesstruct[count] != NULL)          
 {
   count++;    
 }
}
Ich möchte hier prüfen wieviele Items in einem Array stehen. Dazu ist 
steht eine NULL am Ende des Arrays. Jetzt prüfe ich die Adressen im 
Array. So wie es oben im Code steht prüfe ich aber die Adresse des 
Zeigers auf die ArrayItems, oder? Welche Möglichkeiten habe ich direkt 
die Adresse der ArrayItems zu prüfen?

DANKE
Tom

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab jetzt nochmal im Internet etwas gesucht. Aber irgendwie nichts 
gefunden. Gibts da überhaupt eine Möglichkeit?

Tom

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich schonwieder!

@ Karl-Heinz Buchegger
Bei deinem Code bekomm ich einen Stackfehler. Irgendwas stimmt noch 
nicht.
Aber ich bin meinem Latein am Ende. Deshalb seit ihr gefragt :)!
Was mach ich bloß falsch?

Tom

Autor: Ingo Elsen (ogni42)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
count muss vor der Benutzung intialisiert werden:
unsigned char count = 0;

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
is klar, aber darin liegt nicht das Problem.

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In dieser Zeile ist der Fehler. Überleg mal, was du hier machst:

   while (&uebergebenesstruct[count] != NULL)

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Steht im Text, dass das falsch ist. Da wird nämlich überprüft ob die 
Adresse Null ist. Ich möchte dagegen aber prüfen ob das letzte Element 
in dem einen Array Null ist.
Ich weiß nur nicht wie das gehen soll.

Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum setzt du das & vor uebergebenesstruct[count]?

Autor: der mechatroniker (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Preisfrage:

1. Was macht das & da?
2. was möchtest du machen?
3. Welches Zeichen solltest du aus deinem Code löschen?

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
:D Ja klar das "&".

Jetzt bleibt nur noch die Geschichte mit dem Stackoverflow.
Wenn ich die Warnstufe des Compilers hochsetze dann bekomme ich bei 
folgendem Funktionsaufruf einen Fehler (pointer to different objects)
func(structarray);

Vielen Dank
Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ohne den Code zu sehen, den du wirklich benutzt, kann ich leider keine 
Aussage machen.

Der Code aus Beitrag "Re: Zeiger - Knoten im Kopf?" erzeugt 
zumindest durch Rekursion keinen Stackoverflow, weil keine vorhanden 
ist.

Liegt es vielleicht am Prozessor? Daß der einfach nicht genug Speicher 
hat?

Autor: Tom G. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier mal die Auszüge aus dem Code

Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und du bist sicher, daß er in arrayedit abstürzt und nicht in ...?

Was ist das für ein Prozessor?

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler meldet einen Fehler bei

arrayedit (startframes);

Allerdings nur auf erhöhter Warnstufe.
Wenn ich "normal" compile, dann stürzt er bei

while (frame[count] != NULL)
{
    count++;
}

ab.

Prozessor ist ein CS167.

Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du einen Debugger? Wenn ja, geh das Programm mal im ASM-Modus 
durch, dann siehst du bei welchem Befehl es kracht.

An deinem Quelltext liegt es m.A. nicht. Vielleicht sind irgendwelche 
Compiler- oder Linkereinstellungen krumm...

Der Compilefehler dürfte keine Rolle spielen.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Der Compiler meldet einen Fehler

Welchen?

> Allerdings nur auf erhöhter Warnstufe.

Man sollte immer alle Warnungen an haben.

> Wenn ich "normal" compile, dann stürzt er bei
>
> while (frame[count] != NULL)
> {
>     count++;
> }
>
> ab.

Welchen Wert hat count beim Absturz?

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Compiler: C166 Compiler V4.27 von Keil

Count hat den Wert 0 beim Absturz.

Tom

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja der Fehler passiert bei ASM Befehl:

 0498E0:   D4 58 02 00  MOV       R5,[R8+#DPP0:0002H]

Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kannst du dir mal kurz bevor er abstürzt, mit dem Dumpfenster oder einer 
Dumpfunktion des Debuggers den Stack anzeigen lassen? Wieviel freier 
Stack ist vorhanden?

Hast du in den ASM-Modus geschaltet und das Programm mal Schritt für 
Schritt durchgegangen, bis es kracht?

Was ist das für ein Maschinenbefehl, der fehlschlägt?

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>> Der Compiler meldet einen Fehler
>> Welchen?
> Compiler: C166 Compiler V4.27 von Keil

Ich meinte eher, welchen Fehler er meldet.

In deinem Code sehe ich keinen Fehler. Ich würde auch auf einen 
Stack-Overflow tippen, oder du hast dir irgendwo vorher durch einen 
fehlerhaften Pointer-Zugriff den Speicher zerschossen.

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler-Fehler:

*** WARNING C98 IN LINE 46 OF MD\FRAME.C: parameter 1: pointer to 
different objects
parameter 1: pointer to different objects

Das vorher ein Fehler ist kann ich ausschließen, da ich den Code auf das 
kleinst mögliche, spricht dem oben angegebenen Code, reduziert habe.

Ich habe das Programm vorher Schritt für Schritt durchlaufen lassen.
Wie gesagt der Fehler tritt bei diesem ASM Befehl auf.

0498E0:   D4 58 02 00  MOV       R5,[R8+#DPP0:0002H]

Betreffs des Maschinenbefehls und des Stacks muss ich mich erst in die 
Debuggerfunktionen einlesen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tom G. wrote:

> Das vorher ein Fehler ist kann ich ausschließen, da ich den Code auf das
> kleinst mögliche, spricht dem oben angegebenen Code, reduziert habe.

Poste mal den kompletten Code. Obiges ist nicht kompilierbar.
Irgendetwas offensichtliches ist so nicht zu sehen und
die Fehlermeldung des Compilers ist auch nicht sehr aussage-
kräftig.

Schreib den Code nicht neu, sondern kopier ihn mittels Copy&Paste
hier herein. Da kannst auch dein originales File, das du zum
Testen benutzt, als Anhang anhängen.

Autor: Tom G. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich kann den Code leider nicht so veröffentlichen wie ich ihn benutze, 
das der  fertige Codeteil lizenzrechtlich geschützt ist. Wenn ich wieder 
die betreffenden Zeilen rauskopiere und umbennene bin ich wieder so weit 
wie vorher....
Manchmal ist es wirklich so, dass man den Wald vor lauter Bäumen nicht 
mehr sieht.

Ich versuche zu verstehen was der Compiler mit dieser "Warning" sagen 
will:
arrayedit (startframes);
Compiler: parameter 1: pointer to different objects

das mag er aber, da meckert er gar nicht:
arrayedit (&startframes);

Weiß jemand warum?

Tom

Autor: Uhu Uhuhu (uhu)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Warnung ist irrelevant; nur ein Hinweis auf eine Unsitte, die früher 
in C legal und üblich war.

Wahrscheinlich verschwindet sie, wenn du arrayedit so definierst:

   void arrayedit(const xframes **frame)

un wird dir nichts anderes übrig bleiben, als dich in den Debugger 
einzuarbeiten und dich mit der Maschinenebene des Prozessors zu befassen 
- das hat aber noch keinem geschadet.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.