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


von Sebastian S. (bcasso)


Lesenswert?

Hallo,

gibt es eine schnelle/elegante Methode ein Array in einer Struktur mit 
einem anderen Array zu initialsieren? Am Beispiel:
1
struct ram_var
2
  {
3
  char a[20];
4
  char b[20];
5
  char c[20];
6
  }
7
struct ram_var ram;
8
9
char aa[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
10
char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
11
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:
1
for(int i=0;i<20;i++)
2
  {
3
  ram.a[i]=aa[i];
4
  ram.b[i]=bb[i];
5
  ram.c[i]=cc[i];
6
  }

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 User
von tester (Gast)


Lesenswert?

schon mal strncpy(ram.a,aa,20) probiert?

von Floh (Gast)


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?
:-)

von Sebastian S. (bcasso)


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.

von Jean Player (Gast)


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));

von Sebastian S. (bcasso)


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 ;)

von Huch (Gast)


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.

von Sebastian S. (bcasso)


Lesenswert?

@Jean Player

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

Aber gehts auch ohne eine solche Init-Funktion?

von Huch (Gast)


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.

von Sebastian S. (bcasso)


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:
1
const unsigned char test  @0x7c44 = 0xff;
2
const unsigned char aa[12]   @0x7c45 = {0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f};  
3
4
struct ram_var
5
  {
6
  ...
7
  unsigned char stest;
8
  unsigned char a[12];
9
  ...  
10
  }
11
struct ram_var ram @0x300 = 
12
  {
13
  ...
14
  test,                                         //ok
15
  memcpy(ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok
16
  ...
17
  }

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.

von Floh (Gast)


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.
:-)

von Huch (Gast)


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.

von Huch (Gast)


Lesenswert?

1
struct ram_var ram @0x300 = 
2
  {
3
  ...
4
  test,                                         //ok
5
  memcpy(ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok
6
  ...
7
  }

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.

von Huch (Gast)


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.

von Rolf Magnus (Gast)


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:
1
struct ram_var ram @0x300 = 
2
{
3
  0xff,
4
  {0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f}
5
};

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

von Sebastian S. (bcasso)


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:
1
struct ram_var ram @0x300 = 
2
  {
3
  0x60,  //ok, mit hex Werten
4
  200,   //ok, mit dec Werten
5
  test,  //ok, mit Variablen
6
  memcpy(&ram.a, (unsigned char)aa, sizeof(aa)), //NICHT ok, da Array
7
  ...
8
  }
Aber das klappt leider nicht. Habe jetzt die einzelnen Arraywerte 
übergeben, nach dem Schema:
1
struct ram_var ram @0x300 = 
2
  {
3
  ...
4
  a[0]=aa[0],
5
  a[1]=aa[1],
6
  ...
7
  }
Nicht gerade schön, aber selten :)
Mit memcpy, memset, strncpy, if/for-Schleifen funktionierts wirklich nur 
innerhalb einer Funktion.
Bsp.:
1
void InitVars(void)
2
  {
3
  memcpy(&ram.data_rot[0],(unsigned char)data_rot,sizeof(data_rot));
4
  }
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.

von Rufus Τ. F. (rufus) Benutzerseite


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?

von Klaus W. (mfgkw)


Lesenswert?

kannst du kein Englisch?
reine C-Probleme -> pure C -> PC

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

Zurück zur Ausgangsfrage:
Was spricht dagegen, halt die einzelnen Elemente zum
Initialisieren zu verwenden?
1
  struct ram_var
2
  {
3
    char a[20];
4
    char b[20];
5
    char c[20];
6
  };
7
8
  char aa[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
9
  char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
10
  char cc[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
11
12
  struct ram_var ram =
13
    {
14
      { 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] },
15
      { 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] },
16
      { 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] }
17
    };

von Sebastian S. (bcasso)


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.

von Karl H. (kbuchegg)


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
**************
1
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
*************************
1
struct ram_var
2
  {
3
    char a[20];
4
    char b[20];
5
    char c[20];
6
  };
7
8
  char aa[20] = {
9
#include "dataA.inc"
10
  };
11
12
  char bb[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
13
  char cc[20] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
14
15
  struct ram_var ram =
16
    {
17
      {
18
#include "dataA.inc"
19
      },
20
      { 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] },
21
      { 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] }
22
    };

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

von Klaus W. (mfgkw)


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).

von Sebastian S. (bcasso)


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.

von Huch (Gast)


Lesenswert?

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

von Sebastian S. (bcasso)


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.

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.