LPCOpen: Funktionen in Headerfiles

Gast #3635525
Lesenswert?

Hallo,
vor ein paar Jahren habe ich mal etwas C auf den AVR's gemacht. Jetzt 
fange ich mit den Cortex-M0 von NXP an (LPC11C24). Da gibt es jetzt nach 
CMSIS etwas neues als Ersatz: LPCOpen. Nun habe ich da mal reingeschaut. 
In der Datei sysctl_11xx.h stehen dann Funktionen wie z.B.
1
STATIC INLINE void Chip_SYSCTL_Map(CHIP_SYSCTL_BOOT_MODE_REMAP_T remap)
2
{
3
  LPC_SYSCTL->SYSMEMREMAP = (uint32_t) remap;
4
}

Habe ich es falsch in Erinnerung, oder sollten in einem Headerfile keine 
Funktionen stehen? Ich meine es mal so gelernt zu haben, daß im Header 
die Deklaration als "Schnittstelle" steht und im gleichnamigem C-File 
das Headerfile includiert wird und die Funktion selbst.
#3635538
Lesenswert?

Wiedereinsteiger schrieb:

> Habe ich es falsch in Erinnerung, oder sollten in einem Headerfile keine
> Funktionen stehen? Ich meine es mal so gelernt zu haben, daß im Header
> die Deklaration als "Schnittstelle" steht und im gleichnamigem C-File
> das Headerfile includiert wird und die Funktion selbst.

Soweit zur 'reinen Lehre'.

Auf der anderen Seite möchte man aber auch immer wieder mal Funktionen 
haben, die im Grunde nichts anderes tun, als irgendwelche Details zu 
verstecken. Was man allerdings nicht haben möchte ist der Overhead, den 
ein Funktionsaufruf mit sich zieht.
Im Idealfall schafft es der Compiler bei kurzen Funktionen, den 
Funktionskörper an der Stelle des Funktionsaufrufs direkt einzusetzen.

Der COmpiler kann also durch sog. inline-ing aus dem hier
1
int twice( int i )
2
{
3
  return 2*i;
4
}
5

6
void foo( int k )
7
{
8
  int j;
9

10
  j = twice( k );
11
}

das hier machen
1
void foo( int k )
2
{
3
  int j;
4

5
  j = 2 * k;
6
}

indem er den Funktionskörper von 'twice' an der Stelle des Aufrufs 
einsetzt. Das spart natürlich den kompletten Funktionsaufruf und 
ermöglicht unter Umständen weitere Optimierungen.

Damit das aber möglich ist, muss der Compiler logischerweise die 
Funktion in ihrer vollen Pracht sehen. Denn wie soll er denn in
1
void bar( int m )
2
{
3
  set( m );
4
};
den Aufruf von 'set' wegoptimieren, wenn er nicht weiß, wie die Funktion 
set tatsächlich aussieht?

Selbiges hier.
Wenn der Compiler durch
1
STATIC INLINE void Chip_SYSCTL_Map(CHIP_SYSCTL_BOOT_MODE_REMAP_T remap)
2
{
3
  LPC_SYSCTL->SYSMEMREMAP = (uint32_t) remap;
4
}
beim Aufrufer einen Aufruf der Funktion Chip_SYSCTL_Map durch einen 
entsprechenden Registerzugriff LPC_SYSCTL->SYSMEMREMAP ersetzen soll, 
dann ist es unumgänglich, dass er auch den Code der Funktion zu Gesicht 
bekommt
1
#include "sysctl_11xx.h"
2

3
int main()
4
{
5
  Chip_SYSCTL_Map( MODUS );
6
}

Das geht aber nur, wenn die Funktion selber in sysctl_11xx.h enthalten 
ist, denn etwas anderes hat der Compiler ja nicht, wenn er diesen C-Code 
compiliert. Die Attributierung durch STATIC INLINE sorgt dann dafür, 
dass es nicht zu Problemen kommt.

Das bedeutet jetzt nicht, dass man alle Funktionen in Header Files 
steckt. Deine grundsätzliche Sichtweise ist prinzipiell schon in 
Ordnung. Nur gibt es eben auch Funktionen, für die man Ausnahmen macht, 
wenn man dafür etwas wesentliches bekommt.
Gast #3635553
Lesenswert?

Vielen Dank für die ausführliche Erklärung. Wieder was gelernt. Neben 
Schwarz und Weiß gibt es (welch Wunder ...) also auch in C viele 
Grautöne, die man nicht unbedingt beim ersten Lesen eines Buches 
erkennt.
#3635570
Lesenswert?

Wiedereinsteiger schrieb:
> Vielen Dank für die ausführliche Erklärung. Wieder was gelernt. Neben
> Schwarz und Weiß gibt es (welch Wunder ...) also auch in C viele
> Grautöne, die man nicht unbedingt beim ersten Lesen eines Buches
> erkennt.


'One size fits all' funktioniert bei Baseballkappen, aber selten in der 
Programmierung.
Das ganze sind ja 'eher Richtlinien' als in Stein gemeisselte Gesetze.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren