Forum: Mikrocontroller und Digitale Elektronik Code minimieren


von Jens (Gast)


Lesenswert?

Hallo

Ich möchte meine Skills ein wenig erweitern, was C und die Optimierung 
und Minimierung anbelangt.

Ich fange einmal beim Einfachsten an.
1
#define LED_PORT_CLK();             __HAL_RCC_GPIOA_CLK_ENABLE();
2
#define LED_PORT_CLK_2();           __HAL_RCC_GPIOB_CLK_ENABLE();
Gibt es dazu eine Möglichkeit die folgenden 2 Zeilen unter einer 
Definition zusammen zu fassen?


Beim folgenden zeit mir der Compiler keine Fehler an, bin mir aber nicht 
sicher, ob das so korrekt ist.
1
#define LED_PORT_CLK();      __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();

von Sebastian R. (sebastian_r569)


Lesenswert?

Jens schrieb:
> Beim folgenden zeit mir der Compiler keine Fehler an, bin mir aber nicht
> sicher, ob das so korrekt ist.#define LED_PORT_CLK();
> __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();

Ich würde mal sagen, dass LED_PORT_CLK(); mit 
__HAL_RCC_GPIOA_CLK_ENABLE(); definiert wird und danach das 
__HAL_RCC_GPIOB_CLK_ENABLE(); ausgeführt wird.

: Bearbeitet durch User
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jens schrieb:
> #define LED_PORT_CLK();             __HAL_RCC_GPIOA_CLK_ENABLE();
> #define LED_PORT_CLK_2();           __HAL_RCC_GPIOB_CLK_ENABLE();

Sicher dass das da genau so steht mit dem "();" ??

Jens schrieb:
> #define LED_PORT_CLK();      __HAL_RCC_GPIOA_CLK_ENABLE();
> __HAL_RCC_GPIOB_CLK_ENABLE();

Ist so halb korrekt (das "();" ist natürlich Quatsch). Stell dir vor was 
passiert wenn man so etwas schreibt:
1
if (irgendwas)
2
  LED_PORT_CLK();
Daraus wird dann
1
if (irgendwas)
2
  __HAL_RCC_GPIOA_CLK_ENABLE();
3
__HAL_RCC_GPIOB_CLK_ENABLE();
Wahrscheinlich nicht das was man will! Es gibt einen Standard-Trick der 
alle Fälle dieser Art abdeckt:
1
#define LED_PORT_CLK do { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); } while (0)
Das funktioniert in allen if/else/Schleifen-Konstrukten. Allerdings geht 
es auch noch viel besser mit einer Funktion:
1
inline void LED_PORT_CLK() {
2
  __HAL_RCC_GPIOA_CLK_ENABLE();
3
  __HAL_RCC_GPIOB_CLK_ENABLE();
4
}
Erspart den ganzen Ärger mit dem Präprozessor und der Textersetzung, ist 
aber genauso effizient. Wenn man 100% sicher gehen möchte, dass das 
"inline" auch wirklich wirkt, kann man noch 
"__attribute__((always_inline))" hinzufügen. Da aber das Ein/Ausschalten 
von Takten wahrscheinlich sowieso nur 1x beim Programmstart passiert, 
ist dessen Geschwindigkeit dann auch egal und das Sparen von 
Programmspeicher ist hier sinnvoller, weshalb man das "inline" auch 
komplett lassen kann. Wozu hier also überhaupt Makros genutzt werden ist 
daher ohnehin fraglich.

PS: Bezeichner und Makro-Namen welche mit zwei Unterstrichen oder 
Unterstrich+Großbuchstabe anfangen, wie z.B. 
"__HAL_RCC_GPIOA_CLK_ENABLE" sind in C der C-Standard-Bibliothek 
vorenthalten, und somit hier falsch. Ändern kann man das in der 
Cube-Bibliothek eher nicht, aber man sollte solche Fehler nicht 
nachmachen...

von Peter D. (peda)


Lesenswert?

Jens schrieb:
> Gibt es dazu eine Möglichkeit die folgenden 2 Zeilen unter einer
> Definition zusammen zu fassen?

Natürlich. Ein Define geht immer bis zum Zeilenende.
Man sollte aber Seiteneffekte beachten, z.B. wenn es in einem if ohne {} 
aufgerufen wird. Daher sind Klammern zu empfehlen.

von Jens (Gast)


Lesenswert?

Sebastian R. schrieb:
> Jens schrieb:
>> Beim folgenden zeit mir der Compiler keine Fehler an, bin mir aber nicht
>> sicher, ob das so korrekt ist.#define LED_PORT_CLK();
>> __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
>
> Ich würde mal sagen, dass LED_PORT_CLK(); mit
> __HAL_RCC_GPIOA_CLK_ENABLE(); definiert wird und danach das
> __HAL_RCC_GPIOB_CLK_ENABLE(); ausgeführt wird.

Hmm, wenn __HAL_RCC_GPIOB_CLK_ENABLE(); danach ausgeführt wird, könnte 
ich es im h-file genauso in die nächste Zeile schreiben, sprich so:

1
#define LED_PORT_CLK();         __HAL_RCC_GPIOA_CLK_ENABLE(); 
2
__HAL_RCC_GPIOB_CLK_ENABLE();

aber dann kommt ein Fehler, also muss es doch so in einer Zeile eine 
Definition sein, die beide Enables enthält?!
1
*** Using Compiler 'V5.06 update 4 (build 422)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
2
Build target 'xxx'
3
compiling gpio.c...
4
../Inc/tsc.h(89): error:  #169: expected a declaration
5
  
6
_HAL_RCC_GPIOB_CLK_ENABLE();
7
..\Src\gpio.c: 0 warnings, 1 error
8
compiling stm32f0xx_it.c...
9
../Inc/tsc.h(89): error:  #169: expected a declaration
10
  
11
_HAL_RCC_GPIOB_CLK_ENABLE();
12
../Src/stm32f0xx_it.c: 0 warnings, 1 error
13
compiling main.c...
14
../Inc/tsc.h(89): error:  #169: expected a declaration
15
  
16
_HAL_RCC_GPIOB_CLK_ENABLE();
17
../Src/main.c: 0 warnings, 1 error
18
compiling tsc.c...
19
../Inc/tsc.h(89): error:  #169: expected a declaration
20
  
21
_HAL_RCC_GPIOB_CLK_ENABLE();
22
..\Src\tsc.c: 0 warnings, 1 error
23
"xxx - 4 Error(s), 0 Warning(s).
24
Target not created.
25
Build Time Elapsed:  00:00:02 C-Code

von Walter K. (vril1959)


Lesenswert?

#define ist ja nicht so schwer zu verstehen

Als erstes solltes Du mal über das Semikolon nachdenken/nachlesen

Und wenn Du unsicher bist, was der Präprozessor mit
Deinen #define macht ... kannst Du es mit #ifdef testen

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

1
#define LED_PORT_CLK(); { __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); }

1
#define LED_PORT_CLK(); ( \
2
    __HAL_RCC_GPIOA_CLK_ENABLE(); \
3
    __HAL_RCC_GPIOB_CLK_ENABLE(); \
4
)

Aber achtung: Hinter dem Backslash darf kein Whitespace kommen!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Ich hab da auch noch eine überraschende Möglichkeit:
1
#define LED_PORT_CLK();  __HAL_RCC_GPIOA_CLK_ENABLE(), __HAL_RCC_GPIOB_CLK_ENABLE();

Wobei ich prinzipiell nicht kapiere, warum man für diese LED_PORT_CLK 
noch ein extra Define braucht. Ich schreibe da genau die zwei HAL 
Aufrufe in die Initialisierung, und muss nicht noch hinter dem 
LED_PORT_CLK suchen, wenn ich wissen will, welcher Takt da nun letztlich 
verwendet wird...

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


Lesenswert?

Jens schrieb:
> Ich möchte meine Skills ein wenig erweitern, was C
sehr gut!

> und die Optimierung und Minimierung anbelangt.
Es ist gut, wenn Du Dich mit C, seinen Konstrukten und Möglichkeiten 
auseinander setzt.

Was Du da aber betreibst nennt man Obfuscierung und hat mit Optimierung 
oder Minimierung nichts zu tun.

Du kannst z.B. 100 Zeilen hinter einen #define verstecken, aber gut ist 
das nicht.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Warum überhaupt Makros? Muss es wirklich eine Textersetzung sein? Ist 
nicht ein gewöhnlicher Funktionsaufruf einfacher, sauberer, 
fehlersicherer?

von Vn N. (wefwef_s)


Lesenswert?

Jens schrieb:
> Ich möchte meine Skills ein wenig erweitern, was C und die Optimierung
> und Minimierung anbelangt.
>
> Ich fange einmal beim Einfachsten an.#define LED_PORT_CLK();
> __HAL_RCC_GPIOA_CLK_ENABLE();
> #define LED_PORT_CLK_2();           __HAL_RCC_GPIOB_CLK_ENABLE();
> Gibt es dazu eine Möglichkeit die folgenden 2 Zeilen unter einer
> Definition zusammen zu fassen?

Was genau versprichst du dir als Ergebnis davon?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Niklas G. schrieb:
> Ist nicht ein gewöhnlicher Funktionsaufruf einfacher, sauberer,
> fehlersicherer?
Der wird vom Compiler bei so simplem Zeug sowieso inline aufgelöst.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Lothar M. schrieb:
> Der wird vom Compiler bei so simplem Zeug sowieso inline aufgelöst.

Eben. Daher kann man es auf Code-Ebene mit Funktionen besser 
strukturieren.

von Stefan F. (Gast)


Lesenswert?

Lothar M. schrieb:
> Ich hab da auch noch eine überraschende Möglichkeit:

Huch!

Was ist dass denn für eine Syntax, was bewirkt das Komma an dieser 
Stelle?

Niklas G. schrieb:
> man (kann) es auf Code-Ebene mit Funktionen besser strukturieren.

Ja.

von Nop (Gast)


Lesenswert?

Jens schrieb:

> Ich möchte meine Skills ein wenig erweitern, was C und die Optimierung
> und Minimierung anbelangt.

Dafür ist der Präprozessor in diesem Fall der verkehrte Platz, weil er 
nur eine Textersetzung vornimmt. Dein Code wird also weder schneller 
noch kleiner.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Was ist dass denn für eine Syntax, was bewirkt das Komma an dieser
> Stelle?

Das ist der Komma-Operator. Ausdrücke, welche per Komma hintereinander 
gehängt werden, werden alle ausgewertet (d.h. Nebeneffekte ausgeführt), 
aber nur der Rückgabewert des letzten Ausdrucks dann zurückgegeben. Das 
braucht man eigentlich eher selten (hauptsächlich bei fold-expressions 
in C++17 :) ), ist aber für fiese Makro-Konstruktionen bei welchen 
mehrere Dinge auf einmal ausgeführt werden sollen beliebt. Wie gesagt: 
Eine Funktion ist hier sehr wahrscheinlich am besten.

von Stefan F. (Gast)


Lesenswert?

Niklas G. schrieb:
> Ausdrücke, welche per Komma hintereinander
> gehängt werden, werden alle ausgewertet

Danke für die Erklärung. Unfassbar dass ich das nach so vielen Jahren 
noch nie gesehen/gelernt habe.

von Nop (Gast)


Lesenswert?

Stefanus F. schrieb:
> Unfassbar dass ich das nach so vielen Jahren
> noch nie gesehen/gelernt habe.

Wahrscheinlich doch, und zwar wenn Du in einer for-Schleife mehr als nur 
die Schleifenvariable initialisierst.

von Stefan F. (Gast)


Lesenswert?

Stefanus F. schrieb:
>> Unfassbar dass ich das nach so vielen Jahren
>> noch nie gesehen/gelernt habe.

Nop schrieb:
> Wahrscheinlich doch, und zwar wenn Du in einer for-Schleife mehr als nur
> die Schleifenvariable initialisierst.

Habe ich auch noch nie gesehen.

von Jens (Gast)


Lesenswert?

Hallo Niklas

Ich verwende nun die Definition mit dem do und while ausgeführt.

Niklas G. schrieb:
> Jens schrieb:
>> #define LED_PORT_CLK();             __HAL_RCC_GPIOA_CLK_ENABLE();
>> #define LED_PORT_CLK_2();           __HAL_RCC_GPIOB_CLK_ENABLE();
>
> Sicher dass das da genau so steht mit dem "();" ??

In diesem Fall nicht, wenn das mit #ifdef's nicht funktioniert..

>
> Jens schrieb:
>> #define LED_PORT_CLK();      __HAL_RCC_GPIOA_CLK_ENABLE();
>> __HAL_RCC_GPIOB_CLK_ENABLE();
>
> Ist so halb korrekt (das "();" ist natürlich Quatsch).

Das habe ich nun verstanden, aber:

> Stell dir vor was passiert wenn man so etwas schreibt:if (irgendwas)
>   LED_PORT_CLK();Daraus wird dannif (irgendwas)
>   __HAL_RCC_GPIOA_CLK_ENABLE();
> __HAL_RCC_GPIOB_CLK_ENABLE();Wahrscheinlich nicht das was man will!

Abgesehen davon, dass ich dann ein Problem habe mit den ifdef's, aber 
wieso eigentlich nicht? Wieso ist das so falsch oder Quatsch? Das ist 
ziemlich das, was ich wollte.

> Allerdings geht
> es auch noch viel besser mit einer Funktion:inline void LED_PORT_CLK() {
>   __HAL_RCC_GPIOA_CLK_ENABLE();
>   __HAL_RCC_GPIOB_CLK_ENABLE();
> }
> "__attribute__((always_inline))" hinzufügen.

Meinst du so?
1
__attribute__((always_inline)) void LED_PORT_CLK() {
2
>   __HAL_RCC_GPIOA_CLK_ENABLE();
3
>   __HAL_RCC_GPIOB_CLK_ENABLE();
4
> }

D Wozu hier also überhaupt Makros genutzt werden ist
> daher ohnehin fraglich.

Naja, die Ports können frei gewählt werden.
Wenn es mal Port C oder D sein soll, möchte ich nicht, dass man es 
direkt in den fertigen Funktionen herum hantiert. Ich möchte auch, dass 
man mit __HAL_RCC_GPIOA_CLK_ENABLE(); zB einen Port CLK für eine LED 
eingeschaltet hat. Deshalb der Textersatz.

Vielen Dank übrigens auch für die vielen Kommentare von den anderen hier 
im Forum.

Beitrag #5698257 wurde von einem Moderator gelöscht.
von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jens schrieb:
> In diesem Fall nicht, wenn das mit #ifdef's nicht funktioniert..

Was für #ifdef's?

Jens schrieb:
> Wieso ist das so falsch oder Quatsch?

Weil man als Leser nicht sieht was passiert.

Das hier
1
if (irgendwas)
2
  LED_PORT_CLK();
sieht so aus wie "Wenn Bedingung erfüllt, schalte LED-Ports ein.". Es 
wird aber
1
if (irgendwas)
2
  __HAL_RCC_GPIOA_CLK_ENABLE();
3
__HAL_RCC_GPIOB_CLK_ENABLE();
daraus, d.h. "Wenn Bedingung erfüllt, wirt GPIOA aktiviert, und GPIOB 
wird immer aktiviert, egal ob Bedingung erfüllt oder nicht". Schlimmer 
wird es mit Schleifen:
1
while (irgendwas)
2
  LED_PORT_CLK();
Sieht so aus als würden beide LED-Ports wiederholt eingeschaltet. 
Tatsächlich wird aber nur der 1. wiederholt eingeschaltet, und der 2. 
genau einmal. Okay, Ports wird man nicht in Schleifen einschalten, aber 
du wolltest ja lernen wie man es allgemein besser macht.

Jens schrieb:
> Meinst du so?
Nein so:
1
__attribute__((always_inline)) inline void LED_PORT_CLK() {
2
  __HAL_RCC_GPIOA_CLK_ENABLE();
3
  __HAL_RCC_GPIOB_CLK_ENABLE();
4
}

Jens schrieb:
> Naja, die Ports können frei gewählt werden.
Können sie in der Funktion auch.

Jens schrieb:
> Wenn es mal Port C oder D sein soll, möchte ich nicht, dass man es
> direkt in den fertigen Funktionen herum hantiert.
Aber mit fertigen Makros? Um aufrufenden Code ist es überhaupt kein 
Unterschied! Du kannst die LED_PORT_CLK-Funktion doch beliebig ändern, 
um andere Ports einzuschalten.

Jens schrieb:
> Ich möchte auch, dass
> man mit __HAL_RCC_GPIOA_CLK_ENABLE(); zB einen Port CLK für eine LED
> eingeschaltet hat. Deshalb der Textersatz.
Verstehe ich nicht. Dieses Makro ist doch vorgegeben, da kannst du 
ohnehin nichts mit machen.

von Jens (Gast)


Lesenswert?

Niklas G. schrieb:
> Jens schrieb:
>> In diesem Fall nicht, wenn das mit #ifdef's nicht funktioniert..
>
> Was für #ifdef's?
>
Das Beispiel, welches weiter oben der Walter K. erwähnt hat. Das 
funktioniert mit Token am Ende des defines nicht.
>
> Das hierif (irgendwas)
>   LED_PORT_CLK();sieht so aus wie "Wenn Bedingung erfüllt, schalte
> LED-Ports ein.". Es
> wird aberif (irgendwas)
>   __HAL_RCC_GPIOA_CLK_ENABLE();
> __HAL_RCC_GPIOB_CLK_ENABLE();daraus, d.h. "Wenn Bedingung erfüllt, wirt
> GPIOA aktiviert, und GPIOB
> wird immer aktiviert, egal ob Bedingung erfüllt oder nicht". Schlimmer
> wird es mit Schleifen:while (irgendwas)
>   LED_PORT_CLK();Sieht so aus als würden beide LED-Ports wiederholt
> eingeschaltet.
> Tatsächlich wird aber nur der 1. wiederholt eingeschaltet, und der 2.
> genau einmal. Okay, Ports wird man nicht in Schleifen einschalten, aber
> du wolltest ja lernen wie man es allgemein besser macht.
>
Oh mann, ich möchte nicht wissen, an wieviele Dinge ich beim Schreiben 
eines Programm nicht gedacht habe, wenn ich das so lese. Von dieser 
Sicht aus habe ich das nie gesehen.

Ich habe nun eine always inline Funktion erstellt, welcher ich ein 
struct übergebe, die die zu aktivierenden Gruppen enthält.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Jens schrieb:
> Das
> funktioniert mit Token am Ende des defines nicht.

Ich meinte das "();" direkt nach der Definition. Wenn du wirklich
1
#define LED_PORT_CLK();             __HAL_RCC_GPIOA_CLK_ENABLE();
schreibst, wird beim Aufruf des Makros am Anfang ein ";" ausgegeben. Das 
heißt z.B. bei
1
if (bla)
2
  LED_PORT_CLK ();
kommt
1
if (bla)
2
 ; __HAL_RCC_GPIOA_CLK_ENABLE();;
heraus. Das heißt also die Bedingung wird komplett ignoriert und der 
Befehl wird immer ausgeführt. Das ist ziemlich sicher nicht das was du 
willst! Das Semikolon am Ende ist ebenfalls ungünstig, weil du das Makro 
so nicht mit dem Komma-Operator verbinden kannst o.ä. . Also wenn schon:
1
#define LED_PORT_CLK() __HAL_RCC_GPIOA_CLK_ENABLE()
oder einfach
1
#define LED_PORT_CLK __HAL_RCC_GPIOA_CLK_ENABLE

Jens schrieb:
> Von dieser
> Sicht aus habe ich das nie gesehen.
Das ist aber eben genau das, was man bei der Verwendung von 
Präprozessor-Makros immer beachten muss. Daher sind die so gefährlich. 
Wann immer möglich, sollte man deswegen lieber Funktionen oder 
Konstanten benutzen. In C++ geht das auch dank Tempates deutlich besser. 
Es kommen auch noch mehr Gefahren hinzu, z.B. mehrfache Auswertung von 
Argumenten, Namens-Kollisionen, schlecht erkennbare Parameter-Typen, ...

Jens schrieb:
> Ich habe nun eine always inline Funktion erstellt, welcher ich ein
> struct übergebe, die die zu aktivierenden Gruppen enthält.
Okay? Warum war das struct beim Makro nicht nötig?

Also
1
#define LED_PORT_CLK();      __HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE();
wäre besser so
1
#define LED_PORT_CLK() do {__HAL_RCC_GPIOA_CLK_ENABLE(); __HAL_RCC_GPIOB_CLK_ENABLE(); } while (0)
oder eben noch besser
1
__attribute__((always_inline)) inline void LED_PORT_CLK() {
2
  __HAL_RCC_GPIOA_CLK_ENABLE();
3
  __HAL_RCC_GPIOB_CLK_ENABLE();
4
}
Die sind alle genau gleich zu verwenden, via "#define LED_PORT_CLK()", 
nur dass bei letzterem weniger Fehler passieren können. Wo ist hier ein 
struct nötig? Und das "inline"+"always_inline" ist wie gesagt vermutlich 
eher unnötig, weil man hier wahrscheinlich eher auf Platz als auf 
Geschwindigkeit optimieren würde.

von Nop (Gast)


Lesenswert?

Und dann gibt's noch das beliebte do-while-0-Idiom:
1
#define foo() do {bar1(); bar2();} while (0)

Denn wenn man das ohne das do/while macht, also nur mit {}, müßte man es 
mit einem if/else so aufrufen, ohne Semikolon nach foo():
1
if (cond)
2
    foo()
3
else
4
    bla();

Das wäre offensichtlich verwirrend, besonders wenn es mit Semikolon 
einen Compilerfehler gibt.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Nop schrieb:
> Und dann gibt's noch das beliebte do-while-0-Idiom:

Das haben wir doch bereits festgestellt:

Niklas G. schrieb:
> Es gibt einen Standard-Trick der
> alle Fälle dieser Art abdeckt:

Threads ganz lesen...

von Nop (Gast)


Lesenswert?

Niklas G. schrieb:

> Das haben wir doch bereits festgestellt:

Stimmt, aber nicht, wieso das auch das Semikolon-Problem bei if/else 
löst, welches eine einfache Klammerung mit {} hätte.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Nop schrieb:
> Stimmt, aber nicht, wieso das auch das Semikolon-Problem bei if/else
> löst, welches eine einfache Klammerung mit {} hätte.

Ja, das wurde an anderen Stellen schon genug aufgedröselt. Daher hatte 
ich das ausgelassen...

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Stefanus F. schrieb:
> Nop schrieb:
>> Wahrscheinlich doch, und zwar wenn Du in einer for-Schleife mehr als nur
>> die Schleifenvariable initialisierst.
> Habe ich auch noch nie gesehen.
Ist aber ganz praktisch für Einzeiler   ;-)
1
   for (summe=0, cnt=0, idx=endadresse; cnt<anzahl; cnt++, idx--) summe+=array(idx);

: Bearbeitet durch Moderator
von Jens (Gast)


Lesenswert?

Ich habe nun eine weitere Funktion erstellt.

im header
__attribute__((always_inline)) inline void berechne_Differenz(void);

im c-file
1
__attribute__((always_inline)) inline void berechne_Differenz(void)
2
{
3
 
4
tscDiffValue.L1 = tscSampledValue.L1 - tscOnGoingAcValue.LS1;
5
tscDiffValue.L2 = tscSampledValue.L2 - tscOnGoingAcValue.LS2;
6
tscDiffValue.L3 = tscSampledValue.L3 - tscOnGoingAcValue.LS3;
7
}

Im Interrupt habe ich die h-Datei eingebunden und verwende dort die 
Inline Funktion.

#include "kalkulation.h"

berechne_Differenz();

Ich bekomme aber immer wieder die Fehlermeldung
xxx\xxx.axf: Error: L6218E: Undefined symbol berechne_Differenz 
(referred from stm32f0xx_it.o).

Aber warum?

von Niklas Gürtler (Gast)


Lesenswert?

Jens schrieb:
> Aber warum?

Inline Funktionen müssen in dem Header, genau wie Makros.

von Jens (Gast)


Lesenswert?

Niklas Gürtler schrieb:
> Jens schrieb:
>> Aber warum?
>
> Inline Funktionen müssen in dem Header, genau wie Makros.

Vielen Dank ;)

Ich habe für heute eine letzte Frage:
Ich habe zu C nun ein paar Bücher gelesen, aber auf solche Fragen, die 
ich heute gestellt habe, wurde in den Büchern, die ich bisher gelesen 
habe, nie näher eingegangen.
Nun die Frage ist, woher ihr diese Zusatzinformationen habt und welche 
Bücher mir endlich auch mal das Kleingedruckte beibringen.
Ich meine was der Compiler so tut und wie er das und jenes handhabt 
steht doch in keinem C-Buch. Wenn doch, würde ich gerne wissen, wie das 
Buch heisst oder der Link im Internet.

Einen schönen Abend noch.

von Joachim B. (jar)


Lesenswert?

Jens schrieb:
> Ich habe für heute eine letzte Frage:
> Ich habe zu C nun ein paar Bücher gelesen, aber auf solche Fragen, die
> ich heute gestellt habe, wurde in den Büchern, die ich bisher gelesen
> habe, nie näher eingegangen.

ein oder ein paar Bücher reichen nicht, du musst schon ALLE lesen und 
wirst nie alles erfahren!

> Ich meine was der Compiler so tut und wie er das und jenes handhabt
> steht doch in keinem C-Buch. Wenn doch, würde ich gerne wissen, wie das
> Buch heisst oder der Link im Internet.

DAS BUCH gibt es nie, es gibt auch nicht nur einen Compiler, es gibt 
auch nicht nur EIN C sondern K&R C89 C99 und was weiss ich noch wie 
viele Abwandlungen oder Erweiterungen.

Spare das Geld für viele Bücher, K&R ist schon mal ein Anfang und lerne 
durch machen oder in Foren.

von M.A. S. (mse2)


Lesenswert?

Joachim B. schrieb:
> DAS BUCH gibt es nie, es gibt auch nicht nur einen Compiler, es gibt
> auch nicht nur EIN C sondern K&R C89 C99 und was weiss ich noch wie
> viele Abwandlungen oder Erweiterungen.

Dem kann man nur zustimmen aber...

Joachim B. schrieb:
> ... K&R ist schon mal ein Anfang ...
davon würde ich abraten. K&R kennt noch nicht einmal 
Funktionsprototypen, ich würde dringend etwas jüngeres empfehlen...   ;)

: Bearbeitet durch User
von Jens (Gast)


Lesenswert?

M.A. S. schrieb:
> Joachim B. schrieb:
> DAS BUCH gibt es nie, es gibt auch nicht nur einen Compiler, es gibt
> auch nicht nur EIN C sondern K&R C89 C99 und was weiss ich noch wie
> viele Abwandlungen oder Erweiterungen.
>
> Dem kann man nur zustimmen aber...
>
> Joachim B. schrieb:
> ... K&R ist schon mal ein Anfang ...
>
> davon würde ich abraten. K&R kennt noch nicht einmal
> Funktionsprototypen, ich würde dringend etwas jüngeres empfehlen...   ;)

Woher wisst ihr dann, was welcher Compiler macht?
Oder warum zB bei einem#define berechne(); _makro()
der Compiler bei Benutzung von berechne();
; makro; daraus macht?

von Stefan F. (Gast)


Lesenswert?

Jens schrieb:
> Woher wisst ihr dann, was welcher Compiler macht?

Teilweise steht es in der Dokumentation des Compilers. Im Zweifelsfall 
kann man sich vom Compiler ein Assembler-Listing erstellen lassen, das 
man anschliessend analysiert.

Die Zwischenstufe der durch Makros modifizierten Quelltexte, mit denen 
der eigentliche Compiler gefüttert wird, kann man sich mit der gcc 
Option -E ausgeben lassen.

von A. S. (Gast)


Lesenswert?

Jens schrieb:
> Woher wisst ihr dann, was welcher Compiler macht?

eigentlich ist das am Ende egal.

Es gibt für C eine kurze und bindende Vorschrift, was ein Compiler tun 
soll. Für den Anfang nimm die kleinste Norm, "ANSI-C". 
https://de.wikipedia.org/wiki/C_(Programmiersprache)#ANSI_C

Was dort beschrieben ist, setzt heute praktisch jeder Compiler um, die 
paar Veränderungen seither stören für einen ersten Eindruck nicht.

Irgendwelche "Tricks" bewegen sich meist im dort gesteckten Rahmen.

Und sonst halt die http://c-faq.com/ für die wichtigsten und witzigsten 
Effekte

von Jens (Gast)


Lesenswert?

A. S. schrieb:
> Jens schrieb:
> Woher wisst ihr dann, was welcher Compiler macht?
>
> eigentlich ist das am Ende egal.
> Es gibt für C eine kurze und bindende Vorschrift, was ein Compiler tun
> soll. Für den Anfang nimm die kleinste Norm, "ANSI-C".
> https://de.wikipedia.org/wiki/C_(Programmiersprache)#ANSI_C
>
> Was dort beschrieben ist, setzt heute praktisch jeder Compiler um, die
> paar Veränderungen seither stören für einen ersten Eindruck nicht.
>
> Irgendwelche "Tricks" bewegen sich meist im dort gesteckten Rahmen.
> Und sonst halt die http://c-faq.com/ für die wichtigsten und witzigsten
> Effekte

Danke soweit

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
Noch kein Account? Hier anmelden.