C array in sruct mit array initialisieren

OP #1928977
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?
OP #1929009
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.
Gast #1929018
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));
Gast #1929039
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.
OP #1929053
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.
Gast #1929071
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.
:-)
Gast #1929096
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.
Gast #1929098
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.
Gast #1929111
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.
Gast #1929273
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.
OP #1930046
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.
#1930164
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
    };
OP #1930240
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.
#1930246
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.
#1930271
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).
OP #1930295
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.
OP #1934453
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren