Wie man sieht macht CHECK_VALUE momentan noch garnichts, außer den Wert
wieder "zurückzugeben".
Ich wollte nun das Makro dementsprechend erweitern dass
a) weiterhin der Wert zurückgegeben wird
b) mittels assert ein Compile-Zeit Check durchgeführt wird, ob der Wert
im Range ist (Bsp: <= 9)
Das krieg ich nicht hin, also hab ich erstmal geschaut ob ein
_Static_assert in einer Arrayinitialisierung überhaupt klappt:
Der Aufruf erfolgt mittels -std=c11.
Ist das was ich vorhabe überhaupt möglich?
Kann man _Static_assert wirklich nur in Funktionen und "freestanding"
verwenden?
Gibt es andere Lösungen?
Viele Grüße
Ein define macht immer grundsätzlich nur eine Textersetzung. Der
Compiler bekommt das also gar nicht zusehen, der sieht immer nur den
schon aufgelösten Code.
Das sollte deine beiden Fragen beantworten. (die nach dem
static_define, und die die, warum es jetzt nicht geht).
Oliver
Oliver schrieb:> Ein define macht immer grundsätzlich nur eine Textersetzung....
Das ist mir schon klar.
Ich kann auch schreiben:
1
intmyArray[]=
2
{
3
CHECK_VALUE(8),
4
CHECK_VALUE(9),
5
CHECK_VALUE(10)
6
_Static_assert(10<=9,"assert1");
7
};
was natürlich das selbe ist.
Das klappt aber, natürlich mit der gleichen Fehlermeldung, ebenfalls
nicht.
Weswegen ich auch hier nachfrage ob mein Unterfangen nicht durchführbar
ist, d.h. ich _Static_assert einfach falsch verwende.
Ben schrieb:> Weswegen ich auch hier nachfrage ob mein Unterfangen nicht durchführbar> ist, d.h. ich _Static_assert einfach falsch verwende.
Ich denke das kann hier nicht wirklich funktionieren, weil an dieser
Stelle ja nur Initialisierungs-Ausdrücke möglich sind. Ein
_Static_assert ist aber kein Ausdruck, der einen Wert liefern würde.
Daher wäre das logisch gesehen an dieser Stelle schon mal nicht möglich.
Hmm. Ich denke, da musst du zurück zur alten Technik der Präprozessor
#if Anweisungen, so die aufgrund der Datentypen einsetzbar sind.
Karl Heinz schrieb:> _Static_assert ist aber kein Ausdruck, der einen Wert liefern würde.> Daher wäre das logisch gesehen an dieser Stelle schon mal nicht möglich.
Danke KH.
Ich war irgendwie der Meinung, ein _Static_assert würde im OK-Fall zu
"garnix" expandieren, so dass es überall stehen kann.
Die Lösung mit #if ... #error hatte ich schonmal, die funktioniert
grundsätzlich.
Allerdings stelle ich gerade auf ein Array um, so dass ich eine Variable
Anzahl an Einträgen verwalten kann. Dementsprechend wüsste ich nicht,
wie eine Lösung mit #if... hier aussehen würde. Ein #if ist ja erstmal
ein statisches Konstrukt. Ändert sich die Anzahl an Einträgen im Array
müsste der #if Block jedesmal angepasst werden.
Diesen Aufwand wollte ich durch mein CHECK_VALUE Makro direkt bei der
Initialisierung erschlagen.
Gibt es da vielleicht noch einen anderen Weg?
In Terms of syntax, _Static_assert is treated as a declaration statement.
Daher kann das an dieser Stelle nicht funktionieren. Du kannst ja auch
nicht
1
intij[5]={1,2,3,externintk};
schreiben.
> Ich war irgendwie der Meinung, ein _Static_assert würde> im OK-Fall zu "garnix" expandieren, so dass es überall stehen kann.
Das spielt in dem Fall keine Rolle mehr. Die Frage ist, wie
_Static_assert in die Syntax eingebaut wurde.
Soweit OK.
Leider bringt mich das nicht wirklich weiter. Was ich bisher weiß ist,
dass es mit _Static_assert wohl nicht klappen wird. Wenn es eine andere
Lösung gibt wär ich aber auch zufrieden.
Im Prinzip will ich ja sowas hier haben:
1
#define CHECK_VALUE(val) #if (val >= ERROR_VAL) \
2
#error Out of Range! \
3
#else \
4
(val) \
5
#endif
6
7
intmyArray[]=
8
{
9
CHECK_VALUE(8),
10
CHECK_VALUE(9),
11
CHECK_VALUE(10)
12
};
Das der Code nicht kompiliert ist mir klar.
Aber er sollte deutlich machen was ich will. Mit asserts kann ich diese
Funktionalität also nicht erreichen.
Das Beispiel oben klappt auch nicht.
Hat jemand vielleicht noch einen Vorschlag?
Viele Grüße!
Ich verstehe den Sinn nicht so ganz.
Im Normalfall weiß doch der Programmierer am besten, welche Konstanten
er in den Code hinein kompiliert. Warum sollte der Kompiler die
Konstanten noch einmal abprüfen?
Benutzereingaben werden geprüft. Aber das macht ein Programm ja erst zur
Laufzeit und nicht schon zur Kompilierzeit.
Auch wenn der Sinn nicht Thema dieses Threades werden soll:
Es handelt sich um Konfigurationseinträge, die auf Plausibilität geprüft
werden sollen. Ist kein Muss, denn wie du schon sagst sollte der
Programmierer wissen was erlaubt ist und was nicht. Schöner fände ichs
aber wenns nochmal überprüft wird. Allerdings nur, wenn dies zur
Compilezeit möglich ist, denn Ressourcen (ROM oder RAM) will ich dafür
nicht aufwenden.
Beispiel: in sämtlichen UART-Beispielen die man hier findet prüft der
Präprozessor die Baudrate auch nochmal (z.B. ob der Fehler größer 2%
ist).
Dadurch wird verhindert, dass Code kompiliert wird der anschließend
wahrscheinlich nicht zufriedenstellend läuft. Findest du das auch
unsinnig? Ist im Prinzip das gleiche wie ich vorhabe.
Daniel A. schrieb:> #define CHECK_VALUE(val) (_Static_assert (val <= 9, "assert1"), val)
Das funktioniert nicht. Der Compiler meckert schon, wenn man das
static_assert nur umklammert:
1
(static_assert(1,"test"));// [Error] expected expression before '_Static_assert'
Scheinbar funktioniert folgendes:
1
staticconstcharHelp__=' ';
2
#define CHECK(val) (((val) < 10) ? Help__ : val)
Ist val kleiner 10, wirft der Compiler folgende Fehlermeldung:
1
[Error] initializer element is not constant
Etwas unschön, da die Fehlermeldung nicht direkt etwas mit der Prüfung
des Wertes zu tun hat, aber immerhin eine Fehlermeldung.