Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Kommen solche Ausdrücke eigentlich öfter vor?

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: [ 1 ] > 2 < [ 3 ]
010
21.12.2007, 02:41 Uhr
Pablo
Supertux
(Operator)



Zitat von ao:
[quote Pablo]
8-fach geschachtelt, sagst du? Also wenn alle 8 Datentypen mit gleicher Häufigkeit vorkommen, darfst du im statistischen Mittel damit rechnen, dass Vergleich und Verzweigung jeweils 4,5-mal angewendet werden müssen, bis du an der richtigen Stelle gelandet bist. Ich wage zu behaupten, dass ein switch-clause performanter wäre.


Um ehrlich zu sein, gefällt mir die Lösung ganz und gar nicht (könnte damit meinen Code für den obfuscated code contest vorbereiten ), aber ich hab keine bessere Lösung gefunden. Das Problem ist, dass 'data' ein union der Form ist:


C++:
union {
  int8_t     i8;
  uint8_t   u8;
  int16_t   i16;
  uint16_t u16;
  ...
  double d;
}



Die 'sensor' Struktur ist eine "abstrakte Klasse" (das ist eine C Bib) von (nach eigenem Schema) selbst geschriebenen device drivers unterschiedlicher Arten von Sensoren (vor allem CanOpen Geräten und andere Analog Geräten). Diese Sensor Abstraktion hat eine Funktion get_value, die nichts anders ist als ein Wrapper der get_value Funktion der verschiedenen Treiber. Das Problem ist, dass jeder Treiber unterschiedliche Datentypen, so liefern manche Sensoren uint16_t Werte und manche sogar doubles. Deswegen kam ich auf die Idee mit dem Union, so dass je nach Typ des Sensors eins der Felder des Union benutzt, um die Werte des Sensors zu speichern.


Die Idee ist folgende:


C++:
can_device *poti = create_can_device(<params>); /* uint32_t Werte*/
analog_device *pt100 = create_analog_device(<params>); /* double Werte */
...
sensor *s1 = poti->get_abstract_sensor();
sensor *s2 = pt100->get_abstract_sensor();
...
uint32_t val1;
double val2;

val1 = sensor_get_value(val1);
val2 = sensor_get_value(val2);
...



Deswegen kann ich nicht eine sensor_get_value Funktion schreiben, weil die Rückgabe nicht bekannt ist, sondern erst zur Laufzeit bestimmt ist, deswegen ja mein Marko. Außerdem wollen wir nach der Initialisierung nur mit den abstrakten sensor Objekten arbeiten, von denen wir nur wissen (wollen), was für einen Datentyp sie liefern und was das für einen Sensor ursprünglich war.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 21.12.2007 um 02:50 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
011
21.12.2007, 03:57 Uhr
Hans
Library Walker
(Operator)


Hi Pablo,

ich bin mir nicht sicher, ob ich Dein Problem richtig verstanden habe, aber das Makro könntest Du evtl. auch in diesem Stil bauen:

C++:
#ifndef _Test_h
#define _Test_h

typedef struct header* Stapel;

Stapel Init    (int ItSize, int MaxIt);
void   Push    (Stapel s, void* x);
void*  Pop     (Stapel s);
int    isEmpty (Stapel s);
void   Dispose (Stapel s);

#define Create_GStapel(T)                                              \
Stapel Init_##T    (int MaxIt)      { return Init(sizeof(T), MaxIt); } \
void   Push_##T    (Stapel s, T* x) { Push(s, x); }                    \
T*     Pop_##T     (Stapel s)       { return (T*) Pop(s); }            \
int    isEmpty_##T (Stapel s)       { return isEmpty(s);  }            \
void   Dispose_##T (Stapel s)       { Dispose(s);         }            \

#endif


Dieses Beispiel stammt aus dem Buch Softwaretechnik in C und C++ von Rolf Isernhagen, Hanser Verlag, 3. Auflage, Seite 195. Ein paar Kapitel weiter baut er auf diese Weise Container-Strukturen für Stack, Queue, Priorityqueue und noch ein paar andere auf.

Vielleicht lässt sich dieser Stil ja auf Euer Problem übertragen, indem Ihr eine switch - case - Konstruktion in dieser Weise als Makro realisiert. Also

C++:
#define sensor_get_value(sensor) \
  switch (sensor->type)          \
     { case I8 :                 \
            switch (sensor->data->i8) ... \
            break;                        \
       case U8 :                          \
            switch (sensor->data->u8) ... \
            break;                        \
       ...                                \
     }                                    \



Soweit dieser Vorschlag. Was da sonst noch für Seiteneffekte bei auftreten, müsst Ihr heraus finden. Evtl. könnte es später mal Probleme mit der Wartung des Makrocodes geben, wenn es nicht sauber dokumentiert wird. Aber das liegt in Eurer Verantwortung.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
012
21.12.2007, 07:55 Uhr
Windalf
Der wo fast so viele Posts wie FloSoft...
(Operator)



Zitat:

Solchen Code zu lesen ist wie anderen beim Onanieren zuzugucken.


Na dann ist es ja doch ne gute Sache
--
...fleißig wie zwei Weißbrote
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
013
21.12.2007, 13:01 Uhr
Pablo
Supertux
(Operator)


@Hans: sowas (wie in deinem ersten Code) hab schon mal gemacht, allerdings bei einem anderen Projekt (bei einem Echtzeitmikrokernel, den ich für meine Studienarbeit geschrieben hab), aber ich weiß nicht, inwieweit das mir bei meinem jetzigen Problem helfen könnte.

Zu deinem Makro: glaub nicht, dass es sowas geht. Prinzipiel wäre das mir lieber (mit swicth zu arbeiten), aber was ist der Return Wert von der switch Anweisung? Ich will sowas machen wie


C++:
var = sensor_get_value(sensor);



und das würde dann expandieren auf


C++:
var = switch (sensor->type)          \
     { case I8 :                 \
            switch (sensor->data->i8)...



ich denke nicht, dass es geht.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 21.12.2007 um 13:02 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
014
21.12.2007, 21:10 Uhr
Hans
Library Walker
(Operator)


Hi Pablo,

stimmt, das mit dem expandieren könnte sehr lang werden. Anderer Vorschlag:

Zitat von Pablo:
Außerdem wollen wir nach der Initialisierung nur mit den abstrakten sensor Objekten arbeiten, von denen wir nur wissen (wollen), was für einen Datentyp sie liefern und was das für einen Sensor ursprünglich war.


Wenn ihr also noch wissen wollt, was für einen Datentyp die einzelnen Treiber liefern, und die get_value Funktion eh eine Eigenentwicklung ist, dann baut die doch so, das sie 'ne Struktur zurück gibt, in der auch 'ne Information über den Datentyp enthalten ist, etwa so:

C++:
enum sensor_return_type {I8, U8, I16; U16, ... };

struct sensor_data
{ sensor_return_type srt;

  union
   { int8_t   i8;
     uint8_t  u8;
     int16_t  i16;
     uint16_t u16;
     ...
     double   d;
   } return_data;
};



D.h. weil Strukturen ja nicht direkt übergeben werden können, müsste der Funktion ein Zeiger auf die Struktur übergeben werden, über den sie mit Daten gefüllt wird...

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
015
21.12.2007, 22:11 Uhr
Pablo
Supertux
(Operator)



Zitat:

dann baut die doch so, das sie 'ne Struktur zurück gibt, in der auch 'ne Information über den Datentyp enthalten ist, etwa so:



das war von Anfang an so geplannt und ist auch so enthalten und wir übergeben auch nur Ziger auf Strukturen
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
016
22.12.2007, 00:43 Uhr
Hans
Library Walker
(Operator)


Hi Pablo,

dann versteh ich nicht, wieso ihr das hier

C++:

var = sensor_get_value(sensor);


nicht gleich als Funktion ausführt. Wenn Ihr mit den unterschiedlichen Daten noch irgendwie weiter rechnen wollt/müsst, dann müssen die irgendwo normiert, d.h. auf ein einheitliches Format gebracht werden. Wahrscheinlich nach dem Aufruf von sensor_get_value. Und dann muss da auch noch 'ne Anpassung des Wertebereichs hin, damit ihr nicht irgendwann Äpfel mit Birnen vergleicht.
Sonst geht's euch auf einmal wie der NASA bei einer Ihrer letzten Marsmissionen (oder war es der Mond?) wo der Hauptrechner mit Metern rechnete, ein Entfernungssensor seine Daten aber in Meilen und Yards lieferte, weshalb das Ding bei der Landung abgeschmiert ist.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.

Dieser Post wurde am 22.12.2007 um 00:45 Uhr von Hans editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
017
22.12.2007, 02:04 Uhr
Pablo
Supertux
(Operator)


Guter Vergeleich . Mir ist ehrlich gesagt ein Dorn im Auge, dass ich mit so einem Makro arbeite, weil man dadurch schon Birnen und Äpfeln vergleichen kann.

Der Grund, warum ich keine Funktion dafür schreibe, ist dass manchmal ein sensor_get_value manchmal ein uint8_t zurückliefern kann und manchmal ein double oder manchmal int32_t. Was vielleicht besser wäre, das union zurückzuliefern (im Union hab ich zur Zeit nur Grunddatentypen wie int oder double) statt das Element des Unions zurückzuliefern.

Da muss ich aber zuerst mit der Gruppe reden, die die Bib einsetzen wird.
--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
018
22.12.2007, 02:17 Uhr
Hans
Library Walker
(Operator)


Hi,

deshalb doch der Vorschlag mit der Struktur, deren eines Element eine Union ist. Das andere Element ein integer oder char, in dem die Information über den zurückgegebenen Datentyp steckt. In dem Beispiel oben (posting 14) hab ich ein enum verwendet, was ja letztlich int-Werte sind, denen bestimmte Namen zugeordnet werden.

Hans
--
Man muss nicht alles wissen, aber man sollte wissen, wo es steht. Zum Beispiel hier: Nachdenkseiten oder Infoportal Globalisierung.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
019
22.12.2007, 10:53 Uhr
0xdeadbeef
Gott
(Operator)


Man kann structs übrigens durchaus per value übergeben. Oder auch als Rückgabewert. Man übergibt nur deshalb in aller Regel Zeiger, weil das Kopieren eines Zeigers schneller zu machen ist als das eines großen structs.

Was das Designproblem angeht, so würde ich im Zweifel den Rückgabewert als Eigenschaft des Sensors betrachten. Das schreit geradezu nach templates, aber die gibt's in C ja dummerweise nicht...
--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra

Dieser Post wurde am 22.12.2007 um 10:58 Uhr von 0xdeadbeef editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: [ 1 ] > 2 < [ 3 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: