mikrocontroller.net

Forum: Compiler & IDEs struct Name mittels define erstellen - gcc


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Mike (Gast)


Lesenswert?

Guten Morgen,
1
#define APPENDIX "xyz"
2
typedef struct{
3
short var;
4
}structXType_(APPENDIX);
ich würde gerne Strukturen Namen mittels defines erstellen. Klappt so 
nicht, geht das überhaupt? Kommt immer structXType_APPENDIX raus oder es 
lässt sich nicht kompilieren.
GCC

von Yalu X. (yalu) (Moderator)


Lesenswert?

1
##

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Mike schrieb:
> #define APPENDIX "xyz"
> typedef struct{
> short var;
> }structXType_(APPENDIX);

Das würde "}structXType_("xyz");" ergeben.

Wenn überhaupt dann eher so:
1
#define APPENDIX structXType_xyz
2
...}APPENDIX;

Am ende ist das ganze ein simples suchen und ersetzen von Text.

Zusammenfügen von Variabelnname geht nur innerhalb des Macros:
1
#define OwnStruct(a) \
2
struct{ \
3
  short var; \
4
}structXType_##a;
5
6
OwnStruct(xyz);

von Mike (Gast)


Lesenswert?

Yalu X. schrieb:
> ##

kenn ich aber kann ich wohl nicht richtig einsetzen:
1
#define x "structXType_"
2
#define APPENDIX "xyz"
3
#define c(a,b) a##b
4
5
typedef struct{
6
short var;
7
}c(x,APPENDIX);
geht nämlich auch nicht

von Mike (Gast)


Lesenswert?

Irgend W. schrieb:
> #define OwnStruct(a) \
> struct{ \
>   short var; \
> }structXType_##a;
> OwnStruct(xyz);

Danke das klappt aber hab da wohl etwas zu stark verkürzt hätte nämlich 
in der struktur nochmal ein define das geht dann nicht
1
#define OwnStruct(a) \
2
struct{ \
3
#ifdef t1 \
4
  short x; \
5
#endif \
6
}structXType_##a;
7
OwnStruct(xyz);

error: '#' is not followed by a macro parameter

Und nachdem ich da ganze viele verschiedene ifdef Varianten nochmal hab 
kann ich das auch nicht rausnehmen..
An sich sollte die Struktur wo definiert sein und mit config files kann 
man verschiedene typen der Struktur vor dem kompilieren anlegen.

von Yalu X. (yalu) (Moderator)


Lesenswert?

Präprozessordirektiven wie #ifdef, #endif usw. sind innerhalb einer
makrodefinition nicht erlaubt.

Vielleicht solltest du mal etwas weiter ausholen und dein Problem als
Ganzes beschreiben.

: Bearbeitet durch Moderator
von A. S. (achs)


Lesenswert?

Mike schrieb:
> An sich sollte die Struktur wo definiert sein und mit config files kann
> man verschiedene typen der Struktur vor dem kompilieren anlegen.
1
#ifdef t1
2
#define SHORT_X short x;
3
#else
4
#define SHORT_X 
5
#endif
6
7
...
8
   SHORT_X

führt aber ins Chaos. Keine Sau kann das lesen.

Für sowas nehme ich Textfresser (z.B. awk) und mache aus einer config 
datei entsprechenden C-Code (.h/.c).

Vorteil: Du hast am Ende plain C-Code, für Dich, Deinen Debugger, Deine 
IDE, ...

von Kochstudio (Gast)


Lesenswert?

aus dem Kochstudio:

auch CMake kann Configurations Dateien aus Templates anlegen und Texte 
ersetzen

https://cmake.org/cmake/help/v3.18/command/configure_file.html

von foobar (Gast)


Lesenswert?

1
> #define x "structXType_"
2
> #define APPENDIX "xyz"
3
> #define c(a,b) a##b
4
>
5
> typedef struct{
6
>   short var;
7
> }c(x,APPENDIX);
>
>geht nämlich auch nicht

Dann lass die Anführungsstriche weg.

von Bauform B. (bauformb)


Lesenswert?

Mike schrieb:
> ich würde gerne Strukturen Namen mittels defines erstellen. Klappt so
> nicht, geht das überhaupt?

Das geht bestimmt, aber man tut das nicht. Der gcc versucht nur, dich 
schonend auf den rechten Weg zu führen.

von Mitleserin (a.b.) (Gast)


Angehängte Dateien:

Lesenswert?

Bauform B. schrieb:

> Das geht bestimmt, aber man tut das nicht. Der gcc versucht nur, dich
> schonend auf den rechten Weg zu führen.

Das tut man schon und das ist manchmal auch ein richtiger Weg.

*Beispiel in c++*
1
/********************************************
2
 * AVR
3
 * ******************************************
4
 * AUTO_IO_REG_WRAPPER
5
 * ******************************************
6
 * defines each AVR-Register X by MACRO
7
 * ******************************************
8
 * Class          CLASS_NAME for X
9
 * AVR-Register   REG_NAME
10
 * register width DATA_TYPE
11
 * ******************************************
12
 * auto           avoids numerous type casts
13
 ***************************************************************************
14
 * avr-toolchain: ../io.h -> |  addr  |    name   |   type   |
15
 ******#########*************|**####**|***********|**********|*************/
16
 #define AUTO_IO_REG_WRAPPER(REG_NAME, CLASS_NAME, DATA_TYPE)              \
17
                                                                           \
18
  struct CLASS_NAME {                                                      \
19
    using DataT = DATA_TYPE;                                               \
20
                                                                           \
21
    static volatile DataT*  Addr()     {return &REG_NAME                ;} \
22
                                                                           \
23
    static DataT Get       ()          {return  REG_NAME                ;} \
24
    static void  Set       (auto value){        REG_NAME  = DataT(value);} \
25
    static void  Or        (auto value){        REG_NAME |= DataT(value);} \
26
                                                                           \
27
    static void  And       (auto value){        REG_NAME &= DataT(value);} \
28
    static void  Xor       (auto value){        REG_NAME ^= DataT(value);} \
29
                                                                           \
30
    static void  AndOr     (auto andMask,                                  \
31
                            auto orMask ) {     REG_NAME  =                \
32
                                              ( REG_NAME  & DataT( andMask)\
33
                                                          | DataT(orMask);}\
34
    static void  ClrSet    (auto andMask,                                  \
35
                            auto orMask ) {     REG_NAME  =                \
36
                                              ( REG_NAME  & DataT(~andMask)\
37
                                                          | DataT(orMask);}\
38
                                                                           \
39
    static bool  BitIsSet  (auto mask) {return (REG_NAME & DataT(mask));}  \
40
    static bool  BitIsClear(auto mask) {return!(REG_NAME & DataT(mask));}  \
41
  };

Das Makro erstellt eine Register-Klasse für den Zugriff auf auf die 
Hardware -Register z.B. für die Timer von ATtiny-261-461-861 wie im 
Anhang beschrieben.

von Oliver S. (oliverso)


Lesenswert?

Was den Kommentar

Bauform B. schrieb:
> Das geht bestimmt, aber man tut das nicht. Der gcc versucht nur, dich
> schonend auf den rechten Weg zu führen.

äußerst eindrücklich unterstreicht.

Oliver

von Rolf M. (rmagnus)


Lesenswert?

Mitleserin (a.b.) schrieb:
> Das tut man schon

Aber sehr selten.

> und das ist manchmal auch ein richtiger Weg.

Noch seltener.

Ich würde für dein Beispiel einen kleinen Codegenerator mit z.B. Python 
schreiben. Der könnte dann z.B. auch gleich noch automatisch die 
XML-Beschreibungen der I/O-Register einlesen und verarbeiten.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

was soll das denn überhaupt werden? Mir ist das noch zu kurz 
beschrieben. Generell sollte man defines meiden wenn immer es möglich 
ist. Warum soll ein struct überhaupt define abhängig sein?

von Oliver S. (oliverso)


Lesenswert?

Vor allem, warum will man

a) Ein C++-Template durch ein #define-Makro nachbauen
b) überhaupt die Registerzugriffe über Funktionen machen
c) die für alle möglichen Typen per einfachem cast. Wer braucht z.B.
1
AUTO_IO_REG_WRAPPER(TCNT0, VoelligSinnloserStruct, double);

Oliver

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> Generell sollte man defines meiden wenn immer es möglich ist.


Das ist nicht ganz richtig. Solange es lesbar (und das heisst auch: per 
Textsuche auffindbar) ist, spricht nichts dagegen. Als Konfiguration (in 
C) sind defines ein relativ gut standardisiertes und nutzbares Format. 
Vor allem, weil man daraus ganz gute C-Fresser (in analogie zu 
Textfressern) bauen kann.

Was nur unbedingt vermieden werden sollte, ist das erstellen oder nutzen 
von Token, die nicht im Klartext vorliegen. Also genau das, was der TO 
machen will.

Also ein MAX_CURRENT, WITH_ABC oder #define draw() drawLcd1455() sind 
ok.

Ein "int abc(def);", dass zum "int abc_def;" wird (oder noch 
abgefahrener), nicht. Zumindest wenn dessen Scope mehr als ein paar 
Zeilen umfasst.

: Bearbeitet durch User
von Mike (Gast)


Lesenswert?

Guten Morgen,
ok dann bau ich einen Generator. Danke für die Meinungen.

von Kochstudio (Gast)


Lesenswert?

Mike schrieb:
> ok dann bau ich einen Generator.

Eben, da du deine varianten auch steuern musst, wird sowas am besten im 
Make mit integriert. und CMake könnte die Dateien erzeugen ....

von A. S. (achs)


Lesenswert?

Kochstudio schrieb:
> Eben, da du deine varianten auch steuern musst, wird sowas am besten im
> Make mit integriert. und CMake könnte die Dateien erzeugen .

Nun leg doch nicht sofort noch Mühlsteine oben drauf:

Zuerst den Generator. In der für ihn einfachsten Sprache.

Und den immer besser.

Und dann, falls mehr als einmal im Monat gebraucht, in cmake, wenn er 
cmake verwendet.

Oder sein make. Oder seine Batchdatei. Aber das ist Kür. Guten C 
sourcecode zu erstellen.isthier Pflicht

: Bearbeitet durch User
von Sebastian (Gast)


Lesenswert?

Mike schrieb:
> ok dann bau ich einen Generator. Danke für die Meinungen.

Da kann ich auch noch eine Meinung beisteuern: Wenns mit Makros nicht zu 
kompliziert ist (es wurde ja schon festgestellt, dass du nur zu viele 
Anführungszeichen hattest), dann nimm Makros statt eines Generators.

Den Generator musst du nämlich auch pflegen. Und wenn sich der 
generierte Code häufig ändert (sonst könntest du es ja gleich von Hand 
schreiben), ins build-system (make oder cmake?) einbinden. Und dieses 
build-System dann auch noch pflegen.
Und für den Generator musst du noch einen Compiler oder Interpreter mit 
pflegen (den du, falls aller andere Code cross-compiliert ist, nicht 
selbstverständlich hast).

von A. S. (achs)


Lesenswert?

Sebastian schrieb:
> dann nimm Makros statt eines Generators

Das Problem ist, dass die Objekte nicht lesbar sind. Du hast ein 
sObjektABC und keine Möglichkeit, die Definition oder Deklaration zu 
finden.

Und nicht nur Du: auch der Debugger, die IDE, ... .

Prinzipiell sind die Infos im Klartext da, wenn man das ganze durch den 
präprozessor jagt, nur fehlt dann z.b. jeder Kommentar.

von Rolf M. (rmagnus)


Lesenswert?

Sebastian schrieb:
> Mike schrieb:
>> ok dann bau ich einen Generator. Danke für die Meinungen.
>
> Da kann ich auch noch eine Meinung beisteuern: Wenns mit Makros nicht zu
> kompliziert ist (es wurde ja schon festgestellt, dass du nur zu viele
> Anführungszeichen hattest), dann nimm Makros statt eines Generators.

Meine Aussage wäre inhaltlich zwar ähnlich (einfach->Makro, 
kompliziert->Generator), aber ich würd's gerade umgekehrt sagen: Wenn es 
mit Makros nicht sehr einfach ist, bau dir stattdessen einen Generator.
Vor allem ist hier, wie schon von anderen angemerkt, das Problem, dass 
Identifier per Makro zusammengebaut werden.

> Den Generator musst du nämlich auch pflegen. Und wenn sich der
> generierte Code häufig ändert (sonst könntest du es ja gleich von Hand
> schreiben), ins build-system (make oder cmake?) einbinden.
> Und dieses build-System dann auch noch pflegen.

Das ist in der Regel aber nicht besonders schwer. Muss man halt einmal 
rausfinden, wie das geht, und danach kann man das immer wieder 
verwenden.

> Und für den Generator musst du noch einen Compiler oder Interpreter mit
> pflegen (den du, falls aller andere Code cross-compiliert ist, nicht
> selbstverständlich hast).

Ich finde, wer ernsthaft programmiert, sollte sowieso zumindest eine 
Skriptsprache einigermaßen können und dann natürlich auch den 
Interpreter dafür bereits installiert haben. Im Falle von Python und 
Linux (das ist in meinem Fall die Wahl) ist das sowieso schon 
vorinstalliert.
Mit so einer Skriptsprache kann man einerseits solche Generatoren, 
andererseits auch mal ein kleines "wegwerf-Skript" basteln, um schnell 
irgendwas auszuprobieren oder etwas zu erzeugen, das man gerade braucht. 
Ich mache das zumindest öfters.

von Veit D. (devil-elec)


Lesenswert?

A. S. schrieb:
> Veit D. schrieb:
>> Generell sollte man defines meiden wenn immer es möglich ist.
> Das ist nicht ganz richtig. Solange es lesbar (und das heisst auch: per
> Textsuche auffindbar) ...

Hallo,

es ist nicht die Frage ob richtig oder falsch. Die Frage lautet was ist 
besser oder weniger besser. Was ist sicherer oder weniger sicherer.

Ich bin da eben anderer Meinung. defines kann man doppelt und dreifach 
definieren. Das Letzte define gewinnt. Ich habe das schon vertreut im 
Code gesehen wo sich jemand wunderte das es nicht richtig tut.
Maximal kommt eine redefine Warnung (kein Fehler), falls nicht 
unterdrückt.

Ich weiß das C Programmierer ihre defines lieben und man kann damit 
sicherlich sehr viel machen. Aber man kann damit auch sehr viel Mist 
machen. Bspw. bei falscher Klammersetzung.

von Rolf M. (rmagnus)


Lesenswert?

Veit D. schrieb:
> Maximal kommt eine redefine Warnung (kein Fehler), falls nicht
> unterdrückt.

Wer Warnungen unterdrückt oder ignoriert, hat die daraus entstehenden 
Probleme verdient.

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> Ich bin da eben anderer Meinung.
Eine andere Meinung ist ja OK. Doch sind rationale Argumente einfacher 
zu diskutieren.


> defines kann man doppelt und dreifach definieren. Das Letzte define gewinnt. Ich 
habe das schon [...] gesehen

Das ist m.E. kein Argument. Einen etablierten Mechanismus nicht zu 
nutzen, weil andere damit Unsinn machen, hieße auf C in Gänze zu 
verzichten.

Wenn Du hingegen ein  Beispiel hast, dass mit Methode XY besser geht als 
mit #define: Nur zu. Die fehlenden Identifier z.B. sind ein Argument.

von Veit D. (devil-elec)


Lesenswert?

Hallo,

die alles oder nichts Argumentation gefällt mir nicht. Wenn man defines 
in C reduziert wo es möglich ist, wäre schon viel gewonnen. Zum Bsp. 
Konstanten als Konstanten zu schreiben und nicht mit define. Eine define 
"Formel" kann man auch als Funktion schreiben. Das alles heißt noch 
lange nicht das man auf sein C verzichten muss.

von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Zum Bsp. Konstanten als Konstanten zu schreiben und nicht mit define.
Wie genau macht man das? Willst du in jede C-Datei wo Pi gebraucht wird 
ein
1
static const double pi = 3.1413331233;
schreiben?

> Eine define "Formel" kann man auch als Funktion schreiben.
Auch hier ist die Frage, wie du erreichen willst, dass die Funktion die 
gleichen (guten) Eigenschaften hat wie das Makro?

von Rolf M. (rmagnus)


Lesenswert?

Veit D. schrieb:
> die alles oder nichts Argumentation gefällt mir nicht. Wenn man defines
> in C reduziert wo es möglich ist, wäre schon viel gewonnen. Zum Bsp.
> Konstanten als Konstanten zu schreiben und nicht mit define.

Es gibt in C keine Konstanten außer die, die direkt als Wert 
hingeschrieben werden. Deshalb nimmt man dafür ja define. Ich sehe auch 
kein Problem darin, dafür #define zu benutzen.

> Eine define "Formel" kann man auch als Funktion schreiben.

Oft ja, und mit inlining bekommt man genau so optimierten Code.

mh schrieb:
> Veit D. schrieb:
>> Zum Bsp. Konstanten als Konstanten zu schreiben und nicht mit define.
> Wie genau macht man das? Willst du in jede C-Datei wo Pi gebraucht wird
> einstatic const double pi = 3.1413331233;
> schreiben?

Man könnte es in den Header schreiben, genau wie das entsprechende 
#define auch.

>> Eine define "Formel" kann man auch als Funktion schreiben.
> Auch hier ist die Frage, wie du erreichen willst, dass die Funktion die
> gleichen (guten) Eigenschaften hat wie das Makro?

Welches Problem siehst du? Ich sehe nur eins mit so Dingen wie
1
#define MAX(a, b) ((a) > (b) ? (a) : (b))
weil man daraus für jeden Datentyp eine eigene Funktion machen müsste, 
mit eigenem Namen. Aber Veit schreibt ja, dass es für ihn nicht um 
"alles oder nichts" geht. Er möchte Makros möglichst vermeiden, nicht 
komplett abschaffen.

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> Zum Bsp. Konstanten als Konstanten zu schreiben und nicht mit define.
> Eine define "Formel" kann man auch als Funktion schreiben. Das alles
> heißt noch lange nicht das man auf sein C verzichten muss.

Das geht in C++. In C ist das oft Overkill, Dummheit oder gar unmöglich, 
keine defines zu nehmen. Ein Makro hat ganz andere Eigenschaften als 
eine Funktion. Wenn Du kein C magst oder brauchst, dann ist das OK.

Aber Hunde als Haustiere abzulehnen, weil Schlitten von Rentieren 
gezogen werden können, wird niemandem gerecht.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Rolf M. schrieb:
> Man könnte es in den Header schreiben, genau wie das entsprechende
> #define auch.
Nur hat man den Wert dann evtl. mehrfach im RAM und ROM.

Rolf M. schrieb:
> Welches Problem siehst du? Ich sehe nur eins mit so Dingen wie#define
> MAX(a, b) ((a) > (b) ? (a) : (b))
> weil man daraus für jeden Datentyp eine eigene Funktion machen müsste,
> mit eigenem Namen.
Wenn man die Funktion nicht mit static inline in nen header packt, muss 
man für den Funktionsaufruf zahlen.

Rolf M. schrieb:
> Aber Veit schreibt ja, dass es für ihn nicht um
> "alles oder nichts" geht. Er möchte Makros möglichst vermeiden, nicht
> komplett abschaffen.
Und als Beispiel dafür wählt er zwei Beispiele, ohne zu sagen, wann und 
wie man das machen kann.

von A. S. (achs)


Lesenswert?

Rolf M. schrieb:
> Welches Problem siehst du?

Alles wo # oder  ## drin vorkommt.

Alles was im präprozessor passieren muss.

Alles wo 2 token zu einem verschmelzen sollen, ohne ein eigenes Objekt 
zu erschaffen.

von Rolf M. (rmagnus)


Lesenswert?

mh schrieb:
> Rolf M. schrieb:
>> Man könnte es in den Header schreiben, genau wie das entsprechende
>> #define auch.
> Nur hat man den Wert dann evtl. mehrfach im RAM und ROM.

Kommt auf das Optimierungsverhalten des Compilers an. Und bei #define 
hat man das Problem auch. Die Problematik mit const ist eher, dass man 
es nicht überall einsetzen kann, wo ein #define ginge, weil es eben nur 
eine Variable ist, die sich nicht ändert und kein konstanter Ausdruck, 
wie es in C++ wäre.
Auf https://en.cppreference.com/w/c/language/const ist es ganz gut 
zusammengefasst:
"C adopted the const qualifier from C++, but unlike in C++, expressions 
of const-qualified type in C are not constant expressions; they may not 
be used as case labels or to initialize static and thread storage 
duration objects, enumerators, or bit field sizes. When they are used as 
array sizes, the resulting arrays are VLAs."

> Wenn man die Funktion nicht mit static inline in nen header packt, muss
> man für den Funktionsaufruf zahlen.

Ja, also wenn man sie nicht dorthin schreibt, wo auch das Makro stehen 
müsste. Aber seit LTO gilt das auch nicht mehr unbedingt.

von Hans-Georg L. (h-g-l)


Angehängte Dateien:

Lesenswert?

Mit einem sogenannten X-Macro sollte es gehen ...
1
 
2
3
// Liste
4
#define APPENDIX \
5
 X(abc) \
6
 X(def) \
7
 X(ghi) \
8
 X(jkl) 
9
10
// Expansion 
11
#define X(value) \
12
typedef struct { \
13
short var;\
14
} structXType_##value; 
15
APPENDIX 
16
#undef X 
17
18
19
20
main() {
21
22
structXType_abc s1;
23
structXType_def s2;
24
structXType_ghi s3;
25
structXType_jkl s4;
26
27
s1.var = 1;
28
s2.var = 2;
29
s3.var = 3;
30
s4.var = 5;
31
32
return 0;
33
34
}

: Bearbeitet durch User
von Veit D. (devil-elec)


Lesenswert?

Hallo,

Rolf hat mich verstanden.
Es geht um Code den man selbst schreibt. Aber ich bin kein Missionar, 
wollte es nur mal erwähnt haben.
Bsp., nur die assert Meldung bekomme ich nicht hin, dass ginge in C++ 
mit static_assert ganz einfach.
1
#define __ASSERT_USE_STDERR
2
3
#include <avr/io.h>
4
#include <assert.h>
5
6
uint16_t calcBaudrate (const uint32_t targetBaudrate, const uint32_t cpuTakt);
7
uint16_t calcBaudrateError (const uint32_t targetBaudrate, const uint16_t calcBaudValue, const uint32_t cpuTakt);
8
void checkBaudrateError (const uint16_t error);
9
10
const uint32_t BAUDRATE = 300333;    // Baudrate
11
12
/*
13
#define BAUD 250000UL
14
// Berechnungen
15
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden
16
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate
17
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)    // Fehler in Promille, 1000 = kein Fehler.
18
19
#if ((BAUD_ERROR<995) || (BAUD_ERROR>1005))
20
    #error Systematischer Fehler der Baudrate groesser 0,5% und damit zu hoch!
21
#endif
22
*/ 
23
24
int main(void)
25
{
26
    const uint16_t baudrateValue = calcBaudrate (BAUDRATE, F_CPU);
27
    const uint16_t baudrateError = calcBaudrateError(BAUDRATE, baudrateValue, F_CPU);
28
    checkBaudrateError(baudrateError);
29
    UBRR0 = baudrateValue;
30
   
31
    //UBRR0 = UBRR_VAL;
32
    
33
    while (1) 
34
    {
35
    }
36
}
37
38
uint16_t calcBaudrate (const uint32_t targetBaudrate, const uint32_t cpuTakt)
39
{
40
    return (uint16_t) ((1.0 * cpuTakt / 16 / targetBaudrate) - 1) + 0.5;
41
}
42
43
uint16_t calcBaudrateError (const uint32_t targetBaudrate, const uint16_t calcBaudValue, const uint32_t cpuTakt)
44
{
45
    return (uint16_t) (cpuTakt / 16 / (calcBaudValue+1)) * 1000 / targetBaudrate;     
46
}
47
48
void checkBaudrateError (const uint16_t error)
49
{
50
    assert (error >= 995);
51
    assert (error <= 1005);
52
}

von A. S. (achs)


Lesenswert?

Veit D. schrieb:
> Es geht um Code den man selbst schreibt.
Natürlich. Auf anderen hat man wenig Einfluss.

> Bsp., nur die assert Meldung bekomme ich nicht hin, dass ginge in C++
> mit static_assert ganz einfach.

Je nach Compiler mit 0, -1 oder einfach nur anders
1
#define static_assert(exp) extern int _d[exp?1:-1]
2
3
4
static_assert((BAUD_ERROR>995) && (BAUD_ERROR<1005));

Und klar, natürlich ist es sinnlos, für die Baudrate ein #define zu 
nehmen, wenn Du es direkt in Code schreiben kannst. Das hat aber nichts 
mit #define vs Funktion zu tun.

Und natürlich ist es auch sinnlos, ein #define zu nehmen, wenn man 
stattdessen eine inline-Funktion nehmen kann. Das wäre so sinnfrei, wie 
a+a+a+a+a+a statt 6*a um die Multiplikation zu sparen.

: Bearbeitet durch User
von mh (Gast)


Lesenswert?

Veit D. schrieb:
> Bsp., nur die assert Meldung bekomme ich nicht hin, dass ginge in C++
> mit static_assert ganz einfach.

Veit D. schrieb:
> Hallo,
>
> Rolf hat mich verstanden.
> Es geht um Code den man selbst schreibt. Aber ich bin kein Missionar,
> wollte es nur mal erwähnt haben.
> [...]

Was genau soll der Quelltext zeigen? Wenn ich mir das fehlende
1
const uint32_t F_CPU = 16000000;
2
extern volatile char UBRR0;
hinzufüge, produziert der Compiler nen haufen Code (350 Zeilen + calls 
in die Floatingpoint-Lib), der zur Laufzeit ausgeführt werden muss.

Veit D. schrieb:
> Bsp., nur die assert Meldung bekomme ich nicht hin, dass ginge in C++
> mit static_assert ganz einfach.
Ja das geht in C++ ganz einfach, dafür muss man allerdings erstmal den 
ganzen anderen Kram richtig machen.

von mh (Gast)


Lesenswert?

mh schrieb:
> (350 Zeilen + calls in die Floatingpoint-Lib)
Sorry, es sind nur 160 Zeilen + float, hab das -Os verschluckt.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.