mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik C array in sruct mit array initialisieren


Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

gibt es eine schnelle/elegante Methode ein Array in einer Struktur mit 
einem anderen Array zu initialsieren? Am Beispiel:
struct ram_var
  {
  char a[20];
  char b[20];
  char c[20];
  }
struct ram_var ram;

char aa[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
char cc[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};

Gibt es nun eine schnelle Methode wie ich diese Struct-Arrays (a,b,c) 
mit einer einfachen Zuweisung mit den Werten der globalen Arrays 
(aa,bb,cc) befüllen kann? Bisher kenne ich nur den "Umweg" über eine 
Schleife, in der Form:
for(int i=0;i<20;i++)
  {
  ram.a[i]=aa[i];
  ram.b[i]=bb[i];
  ram.c[i]=cc[i];
  }

Das funktioniert zwar... aber geht es auch ohne diese Schleife? Habe es 
auch mit memcpy probiert, aber das funktioniert bei der 
struct-Initialisierung leider nicht. Wer hat eine Idee?

: Verschoben durch Moderator
Autor: tester (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
schon mal strncpy(ram.a,aa,20) probiert?

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Seppel schrieb:
> Das funktioniert zwar... aber geht es auch ohne diese Schleife?

Nein, selbst memcpy ist ja als Schleife realisiert, irgendwann musst du 
die Speicherstellen halt ansprechen.
Würde mir aber jetzt nicht wirklich Gedanken machen drüber, wie oft 
initialiserst du die Arrays schon?
:-)

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Entschuldigt bitte den Schreibfehler in der Überschrift, kanns leider 
nicht mehr ändern: "sruct" = "struct"

strncpy(ram.a,aa,20) geht leider auch nicht. Das Problem ist dabei, dass 
ich ein c-File mit Parametern angelegt habe, welche ich global verwenden 
möchte. In diesem c-File gibt es bisher nur Variablen, zum 
initialisieren mit "strncpy" oder "memcpy" müsste ich eine Funktion 
drumrum bauen.. eine Init-Routine wenn man so will. Das möchte ich aber 
nicht.

Autor: Jean Player (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Seppel schrieb:
> Das funktioniert zwar... aber geht es auch ohne diese Schleife? Habe es
> auch mit memcpy probiert, aber das funktioniert bei der
> struct-Initialisierung leider nicht. Wer hat eine Idee?


Hi, weiss zwar nicht genau was du uns mit diesem Satz sagen willst, aber 
mit memcpy geht das sicherlich :

ram_var* ram;
memcpy(ram->a, aa, sizeof(aa));

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Floh
stimmt schon, man initialisiert nur einmal :) Aber hab halt eine große 
struct von etwa 250 Bytes mit 10 verschieden großen Arrays drin... drum 
frug ich mich grad obs einfacher geht ;)

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du kannst ja die aa,bb,cc Arrays nur einmal halten und die structs mit 
Zeigern darauf initialisieren. Die Zugriffsfunktionen musst Du natürlich 
entsprechend ändern.

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Jean Player

richtig das funktioniert, aber nur wenn ich es in einer Funktion 
aufrufe:
void Init(void)
{
  memcpy(ram.a, aa, sizeof(aa));
}

Aber gehts auch ohne eine solche Init-Funktion?

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Aber gehts auch ohne eine solche Init-Funktion?

Der Punkt ist doch, dass Du willst das ein bestimmer Speicherbereich (in 
der Struktur) Daten enthält, die Du in einem anderen Speicherbereich 
vorhälst.
Es gibt keinen anderen Weg, als die Daten entweder dorthin zu kopieren 
oder die Struktur nochmal unter ausdrücklicher Nennung der Elemente zu 
initialisieren.
Das Problem könnte sicherlich durch entsprechende Sprachmittel anders 
gelöst werden aber C hat solche Sprachmittel nicht und würde, wenn doch, 
nicht darum herumkommen die Daten, ohne das Du das ausdrücklich 
schreibst, doch zu kopieren.

Ich verstehe vielleicht das Grundproblem nicht, aber warum das hier

>müsste ich eine Funktion drumrum bauen.. eine Init-Routine wenn man so >will. Das 
möchte ich aber nicht.
und das hier

>Aber gehts auch ohne eine solche Init-Funktion?

nun zwingend notwendig ist, hast Du bisher leider nicht geschrieben.

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Huch

Nun muss ich doch weiter ausholen.. Zeiger kann ich leider nicht nehmen. 
Meine (aa,bb,cc) sind (nicht wie oben im einfachen Beispiel) Konstanten. 
Im Beispiel heißt das:
const unsigned char test  @0x7c44 = 0xff;
const unsigned char aa[12]   @0x7c45 = {0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};  

struct ram_var
  {
  ...
  unsigned char stest;
  unsigned char a[12];
  ...  
  }
struct ram_var ram @0x300 = 
  {
  ...
  test,                                         //ok
  memcpy(ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok
  ...
  }

Die "@" sind dafür da, damit die Konstanten in die dahinter angegebenen 
Speicherbereiche geschrieben werden. Sie sollen im Flashspeicher stehen, 
daher müssen es Konstanten sein. Wenn ich das selbe mit Variablen mache, 
kommen Fehler, da diese nicht im FLASH Bereich alloziert werden können.

Autor: Floh (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Seppel schrieb:
> Wenn ich das selbe mit Variablen mache,
> kommen Fehler, da diese nicht im FLASH Bereich alloziert werden können.

klar, da meckert der Compiler zu Recht. memcpy wird ja zur Laufzeit 
ausgeführt, nur kann er dann nicht mehr in den Flash schreiben.
Bei "test" funktioniert das, da der Wert bereits zur Compilezeit 
vorliegt und deshalb beim Programmieren durch den Zahlenwert ersetzt 
werden kann.
:-)

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aha. Das hättest Du von Anfang an schreiben sollen.

Du kannst durchaus in Strukturen auch Zeiger auf Vektoren im FLASH 
speichern. Dabei ist es egal, ob die Struktur selbst im RAM oder im 
FLASH liegt.
Nur musst Du eben, wie oben schon bemerkt, die Zugriffsfunktionen 
entsprechend schreiben.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
struct ram_var ram @0x300 = 
  {
  ...
  test,                                         //ok
  memcpy(ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok
  ...
  }

Erlaube mir, Dich höflich darauf hinzuweisen, das Du ein C Buch lesen 
solltest. Du wirst sehen, das in solchen Initialisierungen 
Funktionsaufrufe nicht erlaubt sind. Es sind nur solche Ausdrücke 
möglich, die zur Kompilierzeit zu einer Konstanten auswertbar sind.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du solltest vielleicht auch mal schreiben, auf welcher Hardware das 
Programm laufen soll und welchen Compiler Du benutzt. Du bist hier im 
Unterforum PC-Programmierung. Das ist im Zusammenhang mit Flash-Speicher 
sehr wahrscheinlich ein Widerspruch.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Seppel schrieb:

> Die "@" sind dafür da, damit die Konstanten in die dahinter angegebenen
> Speicherbereiche geschrieben werden.

Warum müssen deine Konstanten denn an einer ganz bestimmten Adresse 
stehen, und warum kannst du deine ram_var nicht direkt mit den 
gewünschten Werten initialisieren?
Also:
struct ram_var ram @0x300 = 
{
  0xff,
  {0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f}
};

Dann kannst du dir deine Flash-Konstanten ganz sparen. Darum kümmert 
sich dann der Compiler für dich.

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich programmiere einen CAN-Bootloader für einen Freescale HCS08 
Controller. Dazu nutze ich die IDE von Freescale (Codewarrior) mit 
integrierten Compiler.
Ich habe diesen Thread in das PC-Programmierungsforum geschrieben, da 
mein Problem ein reines "C" Problem ist. Mir kam halt die Frage auf, ob 
es möglich ist ein Array in einer struct mit einem zweiten Array direkt 
in dieser Initialisierungsliste zu initialisieren, ohne eine Funktion 
oder Schleife aufrufen zu müssen. In dieser Art u Weise:
struct ram_var ram @0x300 = 
  {
  0x60,  //ok, mit hex Werten
  200,   //ok, mit dec Werten
  test,  //ok, mit Variablen
  memcpy(&ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok, da Array
  ...
  }
Aber das klappt leider nicht. Habe jetzt die einzelnen Arraywerte 
übergeben, nach dem Schema:
struct ram_var ram @0x300 = 
  {
  ...
  a[0]=aa[0],
  a[1]=aa[1],
  ...
  }
Nicht gerade schön, aber selten :)
Mit memcpy, memset, strncpy, if/for-Schleifen funktionierts wirklich nur 
innerhalb einer Funktion.
Bsp.:
void InitVars(void)
  {
  memcpy(&ram.data_rot[0],(unsigned char)data_rot,sizeof(data_rot));
  }
Und eben diese Funktion möchte ich nicht einbringen, da es sich um eine 
reine Parameter-File handeln soll.
Danke euch dennoch für eure Hilfe, man lernt ja nie aus.

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Ich habe diesen Thread in das PC-Programmierungsforum geschrieben, da
> mein Problem ein reines "C" Problem ist.

Und? Was haben "reine C-Probleme" mit PC-Programmierung zu tun?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kannst du kein Englisch?
reine C-Probleme -> pure C -> PC

Autor: Rufus Τ. Firefly (rufus) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
PC heißt politically correct. Reine C-Probleme sind das aber nicht.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zurück zur Ausgangsfrage:
Was spricht dagegen, halt die einzelnen Elemente zum
Initialisieren zu verwenden?
  struct ram_var
  {
    char a[20];
    char b[20];
    char c[20];
  };

  char aa[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
  char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
  char cc[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};

  struct ram_var ram =
    {
      { aa[0],aa[1],aa[2],aa[3],aa[4],aa[5],aa[6],aa[7],aa[8],aa[9],aa[10],aa[11],aa[12],aa[13],aa[14],aa[15],aa[16],aa[17],aa[18],aa[19] },
      { bb[0],bb[1],bb[2],bb[3],bb[4],bb[5],bb[6],bb[7],bb[8],bb[9],bb[10],bb[11],bb[12],bb[13],bb[14],bb[15],bb[16],bb[17],bb[18],bb[19] },
      { cc[0],cc[1],cc[2],cc[3],cc[4],cc[5],cc[6],cc[7],cc[8],cc[9],cc[10],cc[11],cc[12],cc[13],cc[14],cc[15],cc[16],cc[17],cc[18],cc[19] }
    };

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Klaus Wachtler
Genau diese Einzelinitialisierung habe ich jetzt auch genommen. Ist halt 
mühselig bei vielen, großen Arrays. Hatte die Hoffnung dass es noch eine 
weitere Methode (außer die oben genannten) gibt, die ich noch nicht 
kenne. Aber gut, es gibt ja 3-4 verschiedene Möglichkeiten. C kann ja 
nix dafür, dass ich so sturköpfig bin und keine Funktion einbinden 
möchte :) Danke euch allen.

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

Bewertung
0 lesenswert
nicht lesenswert
Sebastian Seppel schrieb:
> @ Klaus Wachtler
> Genau diese Einzelinitialisierung habe ich jetzt auch genommen. Ist halt
> mühselig bei vielen, großen Arrays. Hatte die Hoffnung dass es noch eine
> weitere Methode (außer die oben genannten) gibt, die ich noch nicht
> kenne. Aber gut, es gibt ja 3-4 verschiedene Möglichkeiten. C kann ja
> nix dafür, dass ich so sturköpfig bin und keine Funktion einbinden
> möchte :) Danke euch allen.


Es gibt noch eine Möglichkeit. Gar nicht mal so trickreich, wenn man 
erst mal den Brechreiz überwunden hat :-)


file: dataA.inc
**************
0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19

file: irgendwas.h oder .c
*************************
struct ram_var
  {
    char a[20];
    char b[20];
    char c[20];
  };

  char aa[20] = {
#include "dataA.inc"
  };

  char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
  char cc[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};

  struct ram_var ram =
    {
      {
#include "dataA.inc"
      },
      { bb[0],bb[1],bb[2],bb[3],bb[4],bb[5],bb[6],bb[7],bb[8],bb[9],bb[10],bb[11],bb[12],bb[13],bb[14],bb[15],bb[16],bb[17],bb[18],bb[19] },
      { cc[0],cc[1],cc[2],cc[3],cc[4],cc[5],cc[6],cc[7],cc[8],cc[9],cc[10],cc[11],cc[12],cc[13],cc[14],cc[15],cc[16],cc[17],cc[18],cc[19] }
    };

selbiges natürlich sinngemäss für B und C genauso.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oder alternativ statt je eines Include ein #define mit der Liste?
Dann wird nicht das zweite Feld mit dem ersten initialisiert,
sondern beide aus dem Makro.
Ich fürchte allerdings, daß der Compiler nicht merkt, daß die beiden
gleich sind und sie doppelt im Image hält (was für die include-Lösung
auch gilt).

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achja: Weshalb ich diesen Thread in PC-Programmierung eröffnete:
Zitat Forenliste:
"PC-Programmierung - Programmierung auf PCs, allgemeine 
Programmierfragen, ohne direkten Mikrocontrollerbezug."
Da es sich um eine allgemeine Programmierfrage zu C handelt, dachte ich 
passt es am besten darein. Sorry falls das falsch war.

Autor: Huch (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und warum nimmst Du nun keine Zeiger?
Das habe ich noch nicht verstanden.

Autor: Sebastian Seplus (bcasso)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Keine Zeiger -> Weil es ein Zeiger auf den FLASH Bereich werden würde, 
allerdings darf ich zur Laufzeit nicht in den FLASH schreiben. Somit 
muss ich sie erst einmal in den RAM schreiben und anschließend spezielle 
Routinen aufrufen die diesen RAM-Wert in den FLASH schreiben. Ich muss 
also immer den Umweg nehmen: Kopiere RAM in FLASH.

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.