Hallo,
ich habe zwei C Dateien: in der einen solle der struct und
Zugriffsfunktionen deklariert werden und in der Anderen der Zugriff
erfolgen:
//structDatei.c
1
structtest
2
{
3
inti;
4
intx;
5
};
6
staticstructtestTest;
7
8
voidsetStruct_i(intvalue)
9
{
10
Test.i=value;
11
}
12
voidsetStruct_x(intvalue)
13
{
14
Test.x=value;
15
}
Das blöde ist jetzt das ich für jedes Struct-Element eine eigene set
Fuktion schreiben muss.
Ich hätte gerne eine elegantere universelle Methode in etwa so:
void setStruct_int("parameter", int value)
{
Test.“parameter“ = value;
}
„parameter“ gibt das Struct-Element an, welches geändert werden soll.
Hat jemand eine Idee wie man das in C realisieren kann?
Peda schrieb:> „parameter“ gibt das Struct-Element an, welches geändert werden soll.> Hat jemand eine Idee wie man das in C realisieren kann?
Das geht über Arrays und den Index als enum.
ABER:
Warum willst du überhaupt setter wenn die so extrem allgemein sein
sollen? Setter sind selten allgemein weil die bestimmte Invarianten
garantieren sollen, die aber vom jeweiligen Datum abhängen.
Will ich einfach jeden beliebigen Zugriff zulassen, dann kann man auch
gleich direkt auf die Variable zugreifen.
Willst du einen Parameter anhand eines Strings setzen, oder geht es
wirklich nur um die Reduktion von Schreibarbeit?
In letzterem Fall könnte man ein Macro nehmen:
Peda schrieb:> Ich hätte gerne eine elegantere universelle Methode in etwa so:> void setStruct_int("parameter", int value)> {> Test.“parameter“ = value;> }
kannst du doch:
cpp der C-Präprozessor kann man als Vorfahre von Word+VBA ansehen: ein
programmierbares Textverarbeitungssystem das in der Lage ist den Text so
umzuarbeiten dass am Schluss kompilierbares C (ohne, resp. mit
aufgelösten Makros) rauskommt.
Beides ist in etwa ähnlich kryptisch und vergleichbar mit
Verdauungssysteme: wenn man damit arbeitet klebt einem zum Schluss
irgendwie 5che1**e an den Fingern.
---
Wenn man Sowas (structs mit Zugriffsfunktionen) systematisch und "viel"
braucht (z.B. als gemeinsame Basis in heterogenen Systeme wo mit
unterschiedlichen Programmiersprachen und/oder über verschiedene
Architekturen Daten auszutauschen sind) ist man besser dran eine
Datenbeschreibungssprache mit konziser/kompakter Syntax zu verwenden
und davon per Converterprogramm den C-Code generieren zu lassen.
Das lässt sich dann gut auch mit Kompatibilitätschecks ausschmücken (f.
Compiletime & Runtime) was sich beim Debugging in heterogenen Systemen
sehr bezahlt macht.
BTDT, mehrmals & mit Erfolg
pointer schrieb:> struct test t;> set_some_value(&t.x, 1);
Ja, das geht, aber dann gehört dir die Struct eh und dann kannst auch
gleich
t.x = 1;
schreiben - falls du auf die Funktionsprüfung verzichten möchtest.
Peda schrieb:> Das blöde ist jetzt das ich für jedes Struct-Element eine eigene set> Fuktion schreiben muss.> Ich hätte gerne eine elegantere universelle Methode
Also eigentlich, willst du deine Struktur vor falschem setzen
schützen...
und Sie gehört nur dem Modul. OK.
Aber das kannst du auch anders lösen,
anstatt die Technik der Klassen aus C++ nachbilden zu wollen...
ja jetzt schreien gleich wieder alle, aber die Basis des allen ist doch
die gleiche:
Man möchte verhindern, dass falsche Parameter gesetzt werden.
Doch das kann man auch mit einer set Fkt. lösen und nicht für jede
Variable mit einer.
...Denn ob die Struktur nun static im Modul ist und man wird vom
falschen
setzen der Werte gehindert - oder ob man Sie selbst besitzt oder auch
nicht
und gehindert wird...kommt aufs gleiche rauß.
Siehe Anhang.
Adam P. schrieb:> Also eigentlich, willst du deine Struktur vor falschem setzen> schützen...> und Sie gehört nur dem Modul. OK.
Aber nochmal: Was bringt es, eine Struktur "privat" zu halten um dann
doch über eine generelle setter jeglichen Zugriff darauf zu erlauben?
Cyblord -. schrieb:> "privat"
Sie ist nicht "privat", sie gehört dem Modul, es gibt sie nur 1x.
Das war ja sein wunsch.
Klar ist das inkonsistent.
Da würde noch ein "verwalter" hingehören, der jedem anforderer eine neue
instanz gibt (speicherbereich: array of foo_t)
und dann durch ne queue per callback den zugriff verwaltet...aber hey.
er wollte doch nur ne lösung für sein problem um die verwaltung des
zugriffs hatte er ja nicht gefragt ;)
Cyblord -. schrieb:> jeglichen Zugriff darauf zu erlauben?
tut er ja dann nicht, wenn die werte nicht stimmen.
Cyblord -. schrieb:> Aber nochmal: Was bringt es, eine Struktur "privat" zu halten um dann> doch über eine generelle setter jeglichen Zugriff darauf zu erlauben?
Du nimmst dir halt das Interface und kannst es nutzen....falls du es
richtig konfigurierst. Aber es existiert im besten fall nur einmal, oder
als Array mit Job-Queue.
Wenn du eine COM oder UART verwenden willst, hast du auch eine Config.
die du setzen musst. Aber das Objekt kann, muss aber nict bei dir
liegen, das ist alles Design-Sache.
...so nebenbei:
Betriebssysteme erlauben nur den EINEN zugriff auf COM...warum?
Wenn man es doch so möchte, würde das doch auch gehen:
1
Task1Task2
2
\/
3
\/
4
access_mgr
5
|
6
|
7
UART
Mache ich auf dem µc jeden Tag, 1x I²C, aber 5 Devices.
Die Tasks fragen per DMA aber geben den Job in Auftrag und der Manager
kümmert sich drum und gibt ne Callback.
Problem gelöst.
OK, das geht am Thema vorbei, aber wollt nur verdeutlichen, dass man das
"Objekt" nicht immer besitzen muss...alles design sache.
---
Eigentlich wollte der TO nur wissen, wie man eine static gehaltene
varibale im eigenen modul sicher setzen kann...
und um tipp arbeit zu ersparen, kommt ja je aufs gleiche rauß:
get_default_foo
// do anything with your foo
set_my_foo
// and hope ;)
> Ich hätte gerne eine elegantere universelle Methode in etwa so:> void setStruct_int("parameter", int value)> {> Test.“parameter“ = value;> }
Die C Version davon:
struct.h:
1
enumStructElem{ELEM_I,ELEM_X};
2
voidsetStruct(enumStructElemwhat,intvalue);
struct.c
1
#include"struct.h"
2
3
staticstruct{
4
inti;
5
intx;
6
}test;
7
8
voidsetStruct(enumStructElemwhat,intvalue)
9
{
10
switch(what)
11
{
12
caseELEM_I:test.i=value;break;
13
caseELEM_X:test.x=value;break;
14
}
15
}
main.c
1
#include"struct.h"
2
3
...
4
setStruct(ELEM_I,42);
5
setStruct(ELEM_X,0);
Falls der Datentyp von "value" je nach Element unterschiedlich ist (z.B.
int oder double oder pointer), kann man das mit stdarg.h machen.
foobar schrieb:> Die C Version davon:
elegante Idee....
aber ich frag mich ob das so intuitiv beim tippen ist?
will ich wirklich jedes mal angeben, was ich setzen will....
dazu kommt noch der overhead der funktionsaufrufe :
foobar schrieb:>> Ich hätte gerne eine elegantere universelle Methode in etwa so:>> void setStruct_int("parameter", int value)>> {>> Test.“parameter“ = value;>> }>> Die C Version davon:>> struct.h:>
1
>enumStructElem{ELEM_I,ELEM_X};
2
>voidsetStruct(enumStructElemwhat,intvalue);
3
>
>> struct.c>
1
>#include"struct.h"
2
>
3
>staticstruct{
4
>inti;
5
>intx;
6
>}test;
7
>
8
>voidsetStruct(enumStructElemwhat,intvalue)
9
>{
10
>switch(what)
11
>{
12
>caseELEM_I:test.i=value;break;
13
>caseELEM_X:test.x=value;break;
14
>}
15
>}
16
>
Ja, auch solche CodePatterns kommen gerne vor in heterogenen Systemen.
Da dann auch oft die Anzahl Felder in den structs ergo die Anzahl
Einträge für die Enums nicht klein bleibt, werden Wartung und
Erweiterung solchen Codes sehr Disziplinlastig.
Deshalb: Datenbeschreibungsprache --> generierten Code um diese Daten.
oli schrieb:> eine weitere Möglichkeit:>> [c]>> #define OFFSETOF(TYPE, ELEMENT) ((int)&(((TYPE *)0)->ELEMENT))
und wo soll da jetzt der Vorteil gegenüber der schon vorhanden offsetof
sein?
https://en.cppreference.com/w/c/types/offsetof
Irgend W. schrieb:> und wo soll da jetzt der Vorteil gegenüber der schon vorhanden offsetof> sein?
Ist das gleiche Makro!
Es ging nur um die Methodik, wie man das realisiert.
Peda schrieb:> Das blöde ist jetzt das ich für jedes Struct-Element eine eigene set> Fuktion schreiben muss.
Es ist zwar die Frage um wie viele Elemente es geht und welchen Kontext
sie zueinander haben, aber warum ist das blöd? Grundsätzlich sind viele
Funktionen mit geringer Komplexität wartungsfreundlicher als wenige
Funktionen mit hoher Komplexität. Natürlich ist - je nach Anwendungen -
auch oft eine andere Herangehensweise sinnvoll, aber prinzipiell sind
viele Funktionen erst mal nichts schlimmes, wenn man sich dadurch keine
anderen Nachteile einhandelt (doppelter Code, usw.).
Peda schrieb:> Hat jemand eine Idee wie man das in C realisieren kann?
Solange der TO nicht sagt, was er erreichen will, macht keine Antwort
Sinn.
Wenn der setter nur setzt, ist er über. Wenn er mehr macht, kommt es
darauf an, was er machen soll.