Hallo, ich habe ein kleines Problem und finde auf die Schnelle keine Lösung. event.h typedef uint32_t EventMaskType; StatusType SetEvent ( TaskType TaskID, EventMaskType Mask ); task.h typedef uint32_t TaskType; typedef enum { xxx, yyy }TaskStateType; typedef struct { TaskStateType TaskState; EventMaskType ActiveEvents; }OsekOsTaskType; Jetzt brauche ich in event.h einen Include auf task.h wegen dem TaskType. In der task.h brauche ich aber die event.h wegen dem EventMaskType. Damit würden sie sich gegenseitig includieren. Dass kann ich zwar mit #ifndef und so lösen, aber dann findet der Compiler die Typen teilweise nicht. Habt ihr eine Idee?
- Alles in einen Header - Die typedefs in einen dritten Header - Die typedefs duplizieren
Ja, natürlich. Du brauchst bloß deine unsinnigen Typumwandlungen ersatzlos wegzustreichen: typedef uint32_t EventMaskType; typedef uint32_t TaskType; Verrate doch mal der Allgemeinheit, WOZU du diese Verrenkungen eigentlich machst. Im Grunde brauchst du durchweg nix anderes als unsigned long für all deine Events. Mein Eindruck ist, daß du "a la mode" programmierst, also ohne Systematik das hinschreibst, was grad Mode ist. W.S.
Peter schrieb: > - Alles in einen Header > - Die typedefs in einen dritten Header > - Die typedefs duplizieren - Die Deklaration von SetEvent von event.h nach task.h verschieben, wo sie ohnehin besser aufgehoben ist, da die Funktion dazu dient, das Verhalten eines Tasks zu beeinflussen Gibt es Fälle, wo du in einer .c-Datei nur event.h oder nur task.h includen würdest, oder würdest du immer beide zusammen includen? Wenn letzteres der Fall ist, dann würde ich beide Headers zu einem einzigen zusammenschmeißen und diesen task.h nennen. W.S. schrieb: > Du brauchst bloß deine unsinnigen Typumwandlungen ersatzlos > wegzustreichen: > > typedef uint32_t EventMaskType; > typedef uint32_t TaskType; Diese Typsynonyme sind schon sinnvoll, da es nicht naturgegeben ist, dass die Anzahl der Events >16 und ≤32 ist, weswegen man sich nicht für alle Zeiten auf einen bestimmten Integer-Typ festlegen möchte. Durch den Typedef ist der Typ auch zukünftig noch leicht änderbar. Ähnliches gilt auch für den Task-Typ.
:
Bearbeitet durch Moderator
Yalu X. schrieb: > Diese Typsynonyme sind schon sinnvoll, da es nicht naturgegeben ist, > dass die Anzahl der Events >16 und ≤32 ist, weswegen man sich nicht für > alle Zeiten auf einen bestimmten Integer-Typ festlegen möchte. Da knurrt aber bei mir der Blindenhund.. Also, du hast auch keine Erklärung für einen "EventMaskType" und einen "TaskType", wobei dies mit irgend welchen Typsynonymen garnichts zu tun hat. Anstelle irgendwelcher Event-Maskentypen oder dergleichen sollte der TO lieber eine ordentliche Systematik in den definierten Events schaffen. Ich geb dir mal ein Beispiel:
1 | /*
|
2 | Ein Event wird durch ein dword (32bit) dargestellt.
|
3 | Davon
|
4 | die untersten 4 Bit (0..3) sind die Event-Gruppe,
|
5 | die nächsthöheren 8 Bit (4..11) sind Event-ID's innerhalb der Gruppe
|
6 | die übrigen 20 Bits (12.. 31) sind Zusatz-Informationen
|
7 | */
|
8 | |
9 | #define evGruppenMaske 0x00F
|
10 | #define evEventMaske 0xFFF
|
11 | |
12 | /*
|
13 | Hier:
|
14 | 0 = nix, Event gelöscht
|
15 | 1 = Hardware-Events (von Treibern gesendet)
|
16 | 2 = Tastatur-Events (Tasten gedrückt oder losgelassen)
|
17 | 3 = Maus-Events (Position und Tasten)
|
18 | 4 = Menü-Events (menüinterner Broadcast, für menü-interne Organisation)
|
19 | 5 = Timer-Events (Zeitsignale, Botschaften, etc.)
|
20 | 6 = Org-Events (Organisation und Broadcast aus dem Betriebssystem)
|
21 | 7 = Sensor-Events (hier: Positionssensoren)
|
22 | 8 = Error-Events (alles, was mit Fehlern zu tun hat)
|
23 | 9..14 noch undefiniert
|
24 | 15 = App-Events (anwendungsspezifisches Zeugs)
|
25 | */
|
26 | |
27 | /* die Gruppen-Id's */
|
28 | #define idHard 1
|
29 | #define idTast 2
|
30 | #define idMaus 3
|
31 | #define idMenu 4
|
32 | #define idTimer 5
|
33 | #define idOrg 6
|
34 | #define idSensor 7
|
35 | #define idError 8
|
36 | #define idApp 15
|
37 | |
38 | |
39 | /* Gruppe 1 = Hardware-ID's */
|
40 | #define idDrehL ((1<<4) | idHard)
|
41 | #define idDrehR ((2<<4) | idHard)
|
42 | #define idDrehT ((3<<4) | idHard)
|
43 | #define idLTast ((4<<4) | idHard)
|
44 | #define idRTast ((5<<4) | idHard)
|
45 | #define idIrAvail ((10<<4) | idHard)
|
46 | #define idNotHalt ((11<<4) | idHard)
|
47 | |
48 | |
49 | /* Gruppe 2 = Tasten-ID's */
|
50 | #define idKbMake ((0<<4) | idTast)
|
51 | #define idKbBreak ((1<<4) | idTast)
|
52 | /* hierbei: Bit 16..31 ist der WideChar dazu */
|
53 | #define idEnterTaste ((2<<4) | idTast)
|
54 | #define idLinksTaste ((3<<4) | idTast)
|
55 | #define idRechtsTaste ((4<<4) | idTast)
|
56 | #define idRaufTaste ((5<<4) | idTast)
|
57 | #define idRunterTaste ((6<<4) | idTast)
|
58 | #define idEscapeTaste ((7<<4) | idTast)
|
59 | |
60 | #define idTaste0 ((8<<4) | idTast)
|
61 | #define idTaste1 ((9<<4) | idTast)
|
62 | #define idTaste2 ((10<<4) | idTast)
|
63 | #define idTaste3 ((11<<4) | idTast)
|
64 | #define idTaste4 ((12<<4) | idTast)
|
65 | #define idTaste5 ((13<<4) | idTast)
|
66 | #define idTaste6 ((14<<4) | idTast)
|
67 | #define idTaste7 ((15<<4) | idTast)
|
68 | #define idTaste8 ((16<<4) | idTast)
|
69 | #define idTaste9 ((17<<4) | idTast) /* usw. je nach Bedarf */ |
Sowas ist auf einem 32 Bit Controller durchaus passend. Man könnte aber auch einen Event als struct definieren, dann wäre dort mehr Platz für Interna und Werte mit dabei, siehe Eventverwaltung bei Windows. Auf alle Fälle braucht man keine albernen EventMaskType's, sondern stattdessen eine Headerdatei, wo die entscheidenden KENNWERTE eines Events wie im Beispiel zentral definiert sind. Also nochmal zum Mitschreiben: zentral nicht Typen definieren, sondern Inhalte definieren. Schließlich ist der Knackpunkt ja der, daß das Generieren eines Events, dessen Verwaltung (Warteschlange) und dessen Verwertung (Reaktion auf ihn) in ganz unterschiedlichen Programmteilen erfolgt. Das ist ja eben der tiefere Sinn dahinter. Also müssen diese eine zentrale Stelle haben, wo die Inhalte festgelegt sind, aber keine Typdefs's. Hast du das jetzt? W.S.
W.S. schrieb: > Ich geb dir mal ein Beispiel: > ... > Man könnte aber auch einen Event als struct definieren Das ist ja alles schön und gut, geht aber IMHO an dem, was der TE vorhat, komplett vorbei. Das, was du beschreibst, hat Ähnlichkeit mit dem Event-System in GUI-Frameworks. Das, woran der TE gerade arbeitet, liegt aber vermutlich mehrere Ebenen tiefer, so ungefähr auf Scheduler- Ebene eines Betriebssystems oder Echtzeitkernels. Für mich sieht es eher so aus: Es laufen mehrere Tasks, von denen jeder über eine Task-ID identifiziert wird. Diese Task-ID ist einfach eine Integer-Zahl. Um sich nicht für alle Zeiten auf einen bestimmten Wertebereich festlegen zu müssen, hat der TE dafür einen neuen Typnamen definiert. Jeder Task kann auf verschiedene Events reagieren. Diese werden jeweils durch 1 Bit in einer Integer-Zahl repräsentiert. Das Strukturelement ActiveEvents ist entweder die Menge der durch den Task zu bearbeitenden oder die Menge der für den Task freigeschalteten Events. Falls letzteres der Fall sein sollte, wäre allerdings EnabledEvents als Name passender. Dadurch, dass die Eventbits alle in einer einzelnen Integer-Variablen stehen, kann durch Bit-Operationen sehr schnell ermittelt werden, ob ein bestimmtes Event gerade aktiv oder freigeschaltet ist. Da die Anzahl verschiedener Events evtl. noch nicht endgültig feststeht, hat der TE auch hier einen neuen Typnamen definiert. Es kann natürlich sein, dass ich mich irre. Deswegen lassen wir am besten Martin wieder zu Wort kommen.
W.S. schrieb: > Auf alle Fälle braucht man keine albernen EventMaskType's, sondern > stattdessen eine Headerdatei, wo die entscheidenden KENNWERTE eines > Events wie im Beispiel zentral definiert sind. Man braucht eine Headerdatei, in der sowohl der Typ, als auch die Werte definiert sind. Was will ich denn mit den schön sauber definierten Werten, wenn ich mir den passenden Typ bei jeder Verwendung nochmal neu ausdenken muss? > Schließlich ist der Knackpunkt ja der, daß das Generieren eines Events, > dessen Verwaltung (Warteschlange) und dessen Verwertung (Reaktion auf > ihn) in ganz unterschiedlichen Programmteilen erfolgt. Ja eben. Und wenn ich den Typ mal ändern muss, hab ich keine Lust, an X Stellen nachschauen zu müssen, ob der dort gerade verwendete Typ zufällig noch passt. Ich will es an genau einer Stelle im Programm anpassen können. Dafür sind Typedefs da, und sie nicht dafür zu verwenden, ist grober Unfug.
Rolf M. schrieb: > Ja eben. Und wenn ich den Typ mal ändern muss, hab ich keine Lust, an X > Stellen nachschauen zu müssen, ob der dort gerade verwendete Typ > zufällig noch passt. Ich will es an genau einer Stelle im Programm > anpassen können. > Dafür sind Typedefs da, und sie nicht dafür zu verwenden, ist grober > Unfug. Manche leben halt in einer int-Welt ... dort gibts auch kein size_t, ...
W.S. schrieb: > Sowas ist auf einem 32 Bit Controller durchaus passend. Man könnte aber > auch einen Event als struct definieren, dann wäre dort mehr Platz für > Interna und Werte mit dabei, siehe Eventverwaltung bei Windows. Das sollte man auf jeden Fall tun. Denn ein Event ist nun mal kein int! Solange ich typedef (das ist ja nur ein typ-alias und keine Typ-Defintion) verwende, kann ich einen Event implizit in einen anderen ganzzahligen Typen konvertieren. Ich kann also jede Funktion mit einem ganzzahligen Parameter mit einem Event aufrufen. Das ist sicher nicht sinnvoll! Auch C hat ein Typsystem, was man nutzen kann.
1 | typedef uint32_t Event_t; |
2 | |
3 | uint32_t foo(uint16_t x) { |
4 | return 2 * x; |
5 | }
|
6 | |
7 | struct EventSafe { |
8 | uint32_t value; |
9 | };
|
10 | |
11 | int main() { |
12 | Event_t e1 = 1; |
13 | foo(e1); // Quatsch |
14 | |
15 | EventSafe e2 = {2}; |
16 | // foo(e2); // geht so nicht -> gut!
|
17 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.