Forum: Mikrocontroller und Digitale Elektronik structs incrementieren?


von Jan H. (janiiix3)


Lesenswert?

1
typedef struct
2
{
3
  const char *projectName;
4
  const char *hardwareDate;
5
  const char *madeBy;  
6
}DevBoard_t;
7
8
const DevBoard_t *uartMsg = &Message;


Ist es irgendwie möglich auf die einzelnen Strings in dieser Struktur 
via. increment zu kommen?
1
for (uint8_t i = 0 ; i < 3 ; i++)
2
{
3
  uart_puts((char*)(uartMsg++));
4
        uart_puts("\r\n");
5
}

von J. F. (Firma: Père Lachaise) (rect)


Lesenswert?

Schau dir mal pragma packed an.

Mehr: was glaubst du denn?

von Jan H. (janiiix3)


Lesenswert?

J. F. schrieb:
> Schau dir mal pragma packed an.
>
> Mehr: was glaubst du denn?

Geht bestimmt irgendwie..

von Teddy (Gast)


Lesenswert?

Du hast den Struct als Zeiger definiert. Ist das richtig?

Ich wäre so vorgegangen. Den Struct ganz "normal" als Variable, kein 
Zeiger, definiert.
Dann einen pointer, der auf die Anfangsadresse des Structs zeigt 
definiert.
Wenn man dann den pointer incrementiert, müsste er auf das nächste 
Element zeigen.

von Peter D. (peda)


Lesenswert?

Du kannst eine Union aus dem Struct und einem Array definieren. Das 
Array kannst Du dann hochzählen.

von Jan H. (janiiix3)


Lesenswert?

Teddy schrieb:
> Du hast den Struct als Zeiger definiert. Ist das richtig?
>
> Ich wäre so vorgegangen. Den Struct ganz "normal" als Variable, kein
> Zeiger, definiert.
> Dann einen pointer, der auf die Anfangsadresse des Structs zeigt
> definiert.
> Wenn man dann den pointer incrementiert, müsste er auf das nächste
> Element zeigen.

Genau so habe Ich das getan. Das klappt eben nicht..

von Teddy (Gast)


Lesenswert?

Ich denke so:

typedef struct
{
  const char projectName;
  const char hardwareDate;
  const char madeBy;
}DevBoard_t;

const DevBoard_t uartMsg;

const char *ptr = &uartMsg;

von Jan H. (janiiix3)


Lesenswert?

Peter D. schrieb:
> Du kannst eine Union aus dem Struct und einem Array definieren.
> Das
> Array kannst Du dann hochzählen.

Wie genau meinst du das?

von Jan H. (janiiix3)


Lesenswert?

Teddy schrieb:
> Ich denke so:
>
> typedef struct
> {
>   const char projectName;
>   const char hardwareDate;
>   const char madeBy;
> }DevBoard_t;
>
> const DevBoard_t uartMsg;
>
> const char *ptr = &uartMsg;

Das haut so leider nicht hin.

von micha (Gast)


Lesenswert?

ist IMHO undefiniertes Verhalten, aber wenn du Dich darauf verlässt dass 
die Element in der gleichen Reihenfolge und ohne padding hintereinander 
im Speicher liegen und der Anfang des structs identisch mit seinem 
ersten element ist, dann sollte es gehen.

Wenn der struct aber ehe nur die gleichen Element-typen (const char *) 
beinhaltet solltest Du einfach ein array nutzen, dann klappts auch mit 
der pointer-arithmetic :-)

von Jan H. (janiiix3)


Lesenswert?

micha schrieb:
> ist IMHO undefiniertes Verhalten, aber wenn du Dich darauf
> verlässt dass
> die Element in der gleichen Reihenfolge und ohne padding hintereinander
> im Speicher liegen und der Anfang des structs identisch mit seinem
> ersten element ist, dann sollte es gehen.
>
> Wenn der struct aber ehe nur die gleichen Element-typen (const char *)
> beinhaltet solltest Du einfach ein array nutzen, dann klappts auch mit
> der pointer-arithmetic :-)

Wie würde das denn dann aussehen?
1
union test
2
{
3
  DevBoard_t Message;
4
  char uartMsg[];
5
};
So ungefähr?

von Wilhelm M. (wimalopaan)


Lesenswert?

Jan H. schrieb:
> micha schrieb:
>> ist IMHO undefiniertes Verhalten, aber wenn du Dich darauf
>> verlässt dass
>> die Element in der gleichen Reihenfolge und ohne padding hintereinander
>> im Speicher liegen und der Anfang des structs identisch mit seinem
>> ersten element ist, dann sollte es gehen.
>>
>> Wenn der struct aber ehe nur die gleichen Element-typen (const char *)
>> beinhaltet solltest Du einfach ein array nutzen, dann klappts auch mit
>> der pointer-arithmetic :-)
>
> Wie würde das denn dann aussehen?
>
1
> union test
2
> {
3
>   DevBoard_t Message;
4
>   char uartMsg[];
5
> };
6
>
> So ungefähr?

Wenn die einzelnen C-Strings in DevBoard_t 0-terminated sind (wie es bei 
C-Strings angenommen wird), dann wird nur der erste String in DevBoard_t 
ausgegeben.

Edit: Sehe gerade, dass die Elemente in DecBoard_t gar keine char-Arrays 
sind, dann geht das natürlich so eh nicht.

Warum gibst Du die C-Strings nicht einfach direkt aus, statt so ein 
type-punning einzubauen (was zugegebenermaßen in C erlaubt und kein UB 
ist).

: Bearbeitet durch User
von Kirsch (Gast)


Lesenswert?

Jan H. schrieb:
> typedef struct
> {
>   const char *projectName;
>   const char *hardwareDate;
>   const char *madeBy;
> }DevBoard_t;
>
> const DevBoard_t *uartMsg = &Message;
>
> Ist es irgendwie möglich auf die einzelnen Strings in dieser Struktur
> via. increment zu kommen?for (uint8_t i = 0 ; i < 3 ; i++)
> {
>   uart_puts((char*)(uartMsg++));
>         uart_puts("\r\n");
> }

typedef struct {
    const char *projectName;
    const char *hardwareDate;
    const char *madeBy;
} DevBoard_t;

char** test = ()

von Jan H. (janiiix3)


Lesenswert?

Kirsch schrieb:
> char** test = ()

Und was zuweisen?

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Ist es irgendwie möglich auf die einzelnen Strings in dieser Struktur
> via. increment zu kommen?

Vielleicht ein Array mit benamten Indices anstatt Komponenten?  Eine 
Union wie oben genannt geht zwar auch, aber die Lesbarkeit solcher 
Konstrukte ist nicht sooo toll.

Beispiel:
1
enum
2
{
3
    ID_ProjectName,
4
    ID_HardwareDate,
5
    ID_MadeBy,
6
    ID_Count
7
};
8
9
typedef struct
10
{
11
  const char *strings[ID_Count];
12
} DevBoard_t;
13
14
const DevBoard_t Message =
15
{
16
    {
17
        [ID_ProjectName] = "Project",
18
        [ID_HardwareDate] = "Now",
19
        [ID_MadeBy] = "Me"
20
    }
21
};
22
23
const DevBoard_t *uartMsg = &Message;
24
extern void uart_puts (const char*);
25
26
void func (const DevBoard_t *board)
27
{
28
    for (int i = 0; i < ID_Count; i++)
29
    {
30
        uart_puts (board->strings[i]);
31
    }
32
    
33
    const char *const *str = board->strings;
34
35
    for (int i = 0; i < ID_Count; i++)
36
    {
37
        uart_puts (*str++);
38
    }
39
}

von Jan H. (janiiix3)


Lesenswert?

Johann L. schrieb:
> Vielleicht ein Array mit benamten Indices anstatt Komponenten?  Eine
> Union wie oben genannt geht zwar auch, aber die Lesbarkeit solcher
> Konstrukte ist nicht sooo toll.

Wie würde es denn mit einem "union" aussehen?

von Wilhelm M. (wimalopaan)


Lesenswert?

Etwa so:
1
typedef struct {
2
  const char *projectName;
3
  const char *hardwareDate;
4
  const char *madeBy;  
5
} DevBoard_t;
6
7
typedef union {
8
    DevBoard_t db;
9
    const char* array[3];
10
} Strings;
11
12
int main() {
13
    DevBoard_t db = {"abc", "def", "ghi"};
14
    Strings s = {db};
15
16
    printf("n: %s\n", s.array[0]);    
17
    printf("h: %s\n", s.array[1]);    
18
    printf("m: %s\n", s.array[2]);    
19
    
20
    const char** ptr = s.array;
21
22
    printf("n: %s\n", *ptr++);    
23
    printf("h: %s\n", *ptr++);    
24
    printf("m: %s\n", *ptr);    
25
}

Aber gut ist das nicht.

Besser schreibst Du eine eigene Funktion (in C) oder überlädst (in C++) 
eine entsprechende Ausgabefunktion.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Johann L. schrieb:
> Beispiel:
> enum
> {
>     ID_ProjectName,
>     ID_HardwareDate,
>     ID_MadeBy,
>     ID_Count
> };
>
> typedef struct
> {
>   const char *strings[ID_Count];
> } DevBoard_t;
>
> const DevBoard_t Message =
> {
>     {
>         [ID_ProjectName] = "Project",
>         [ID_HardwareDate] = "Now",
>         [ID_MadeBy] = "Me"
>     }
> };
Diese Lösung finde ich recht interessant.
Wie sieht es mit einem "String Array" aus? Kann Ich das da auch so 
einfach einbinden?
1
     char *name[x];

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Jan H. schrieb:
> Diese Lösung finde ich recht interessant.
> Wie sieht es mit einem "String Array" aus? Kann Ich das da auch so
> einfach einbinden?

Das kommt auf die Anwendung an ob das besser ist:
1
enum { ... };
2
3
#define MAX_LEN 10
4
5
typedef struct
6
{
7
  const char strings[ID_Count][MAX_LEN];
8
} DevBoard_t;
9
10
const DevBoard_t Message =
11
{
12
    {
13
        [ID_ProjectName] = "Project",
14
        [ID_HardwareDate] = "Now",
15
        [ID_MadeBy] = "Me"
16
    }
17
};
18
19
extern void uart_puts (const char*);
20
21
const DevBoard_t *uartMsg = &Message;
22
23
void func (const DevBoard_t *board)
24
{
25
    for (int i = 0; i < ID_Count; i++)
26
    {
27
        uart_puts (board->strings[i]);
28
    }
29
    
30
    const char (*str)[MAX_LEN] = board->strings;
31
32
    for (int i = 0; i < ID_Count; i++)
33
    {
34
        uart_puts (*str++);
35
    }
36
}

Ein Problem ist, dass die maximale String-Länge statisch bekannt sein 
muss. Und während man ein const char* ändern und auf einen anderen 
String zeigen lassen kann, ist das bei einem const char[] nicht so.  Und 
ohne das "const" brauch man ein strcpy um einen neuen String 
hineinzubekommen.  Dafür brauch man beim Zugriff eine Indirektion 
weniger und keinen Platz zum Speichern der Adressen, allerdings gibt es 
auch Verschnitt bei ungleich langen Strings.

von Daniel A. (daniel-a)


Lesenswert?

Ich denke hier wäre ein Array angebrachter. Beispiel:
http://rextester.com/NUW57351
1
#include <stdio.h>
2
3
#define DEVBOARD_INFO \
4
  X(PROJECT_NAME, "Name des Projekts") \
5
  X(HARDWARE_DATE, "Herstelldatum des Geräts") \
6
  X(MADE_BY, "Hergestellt von")
7
8
enum devboard_entries {
9
#define X(N,D) DEVBOARD_INFO_ ## N,
10
DEVBOARD_INFO
11
#undef X
12
DEVBOARD_INFO_COUNT
13
};
14
15
const char* devboard_info_description[] = {
16
#define X(N,D) D,
17
DEVBOARD_INFO
18
#undef X
19
};
20
21
typedef const char* devboard_info_t[DEVBOARD_INFO_COUNT];
22
23
devboard_info_t devboard = {
24
  [DEVBOARD_INFO_PROJECT_NAME] = "Mein Projekt",
25
  [DEVBOARD_INFO_HARDWARE_DATE] = "1970-1-1",
26
  [DEVBOARD_INFO_MADE_BY] = "mir",
27
};
28
29
void print_devboard_info(devboard_info_t info){
30
  for( int i=0; i<DEVBOARD_INFO_COUNT; i++ ){
31
    printf("%s: %s\n", devboard_info_description[i], info[i]);
32
  }
33
}
34
35
int main(){
36
  print_devboard_info(devboard);
37
}

Edit: war mal wieder zu spät...

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Johann L. schrieb:
> Jan H. schrieb:
> Diese Lösung finde ich recht interessant.
> Wie sieht es mit einem "String Array" aus? Kann Ich das da auch so
> einfach einbinden?
>
> Das kommt auf die Anwendung an ob das besser ist:enum { ... };
Deine erste Lösung reicht mir. Scheint erstmal perfekt zu passen.

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.