Forum: Mikrocontroller und Digitale Elektronik Dateien verschieben in C


von Taw U. (tawo20)


Lesenswert?

moin zusammen
Erstens bin Anfänger in C :)

Wie verschiebe ich den Code von 2 Funktionen die sich in einer 
Headerdatei befinden in eine andere Datei (Bsp.: in die Datei 
meineDatei.c)

Wie verschiebe ich danach das Mainprogramm in eine andere Datei 
(BSp:mymain.c)

von Trolljäger (Gast)


Lesenswert?

Ausgliederung in eine C Datei und dann #include???

War das ernst gemeint???

von User (Gast)


Lesenswert?

#include macht nichts anderen als den Inhalt der Datei an der Stelle an 
der das include steht einzufügen.

von User (Gast)


Lesenswert?

du kannst auch
#include "foo.bar" schreiben

von HildeK (Gast)


Lesenswert?

Selektieren, Ctrl-X, am Zielplatz Ctrl-V?
Oder was meinst du?

Abgesehen davon: C-Funktionen gehören nicht in eine Headerdatei.

von Maxim B. (max182)


Lesenswert?

HildeK schrieb:
> Abgesehen davon: C-Funktionen gehören nicht in eine Headerdatei.

Wieso? Ich schreibe alle inline-C-Funktionen immer in einer Headerdatei.

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Wieso? Ich schreibe alle inline-C-Funktionen immer in einer Headerdatei.

Auch wenn es mir einerseits widerstrebt dir zuzustimmen.
Hier stimme ich dir aus vollem Herzen zu.

von static (Gast)


Lesenswert?

Ich stimme nicht zu.

Diese inline-Funktionen müssen static sein. Und dann kann man inline 
auch weglassen.

von Einer K. (Gast)


Lesenswert?

static schrieb:
> Ich stimme nicht zu.
>
> Diese inline-Funktionen müssen static sein. Und dann kann man inline
> auch weglassen.
Es mag mit manchen (alten?) Compilern Probleme geben...

Aber in der Regel ist es mittlerweile egal, ob du Funktionen als static 
oder inline deklarierst. Oder auch beides.
Das eine impliziert das andere.

Wobei bei inline die ein oder andere Warnung weniger kommt.

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> Aber in der Regel ist es mittlerweile egal, ob du Funktionen als static
> oder inline deklarierst. Oder auch beides.
> Das eine impliziert das andere.

Will man wirklich inline bekommen, reicht manchmal einfache "static 
inline" nicht. Man muß noch Prototype schreiben, so etwa:
static _inline_ void foo(void) __attribute__((_always_inline_));

Macht man das nicht, so wird Compiler wahrscheinlich versuchen, kluger 
als Programmierer zu werden.

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> __attribute__((always_inline));

Das steht bei (fast?) allen modernen Kompilern dabei, das ein einfaches 
inline nur eine Empfehlung ist.
Keinesfalls verpflichtend.
Und z.B. bei gcc -O0 gar nicht zur Geltung kommt.

Zudem kann man bei hohen Optimierungstufen JEDE Funktion als inline 
annehmen. Es ist also quasi zu einem default Attribut geworden. Der 
Optimizer entscheidet das anhand seiner Regeln.

__attribute__((always_inline)) macht besonders Sinn, wenn man auch bei 
niedriger Optimierungstufe ein inlinig erzwingen muss/möchte.

---

Aber hier, dreht es sich eher um den Sichtbarkeitsbereich, also ob der 
Linker es zu sehen bekommt.
Und da spielt es in gcc C keine Rolle, ob man static oder inline 
verwendet.
Es stören dann nur die Warnings, welche bei inline nicht auftreten.
1
In file included from c:\temp\arduino_build_848181\sketch\s.c:1:
2
c:\temp\arduino_build_848181\sketch\test.h:16:12: warning: 't' defined but not used [-Wunused-function]
3
   16 | static int t(int a)
4
      |            ^

von Stefan F. (Gast)


Lesenswert?

Um zur Ursprungsfrage zurück zu kommen:

Ich würde dafür die Zwischenablage benutzen. Den Block markieren und 
dann mit Strg-X ausschneiden. Danach an einer anderen Stelle mit Strg-V 
einfügen.

(Generation Smartphone bekommt das nicht mehr mit der Muttermilch)

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> Und z.B. bei gcc -O0 gar nicht zur Geltung kommt

Benutzt du diese Einstellung???

Arduino Fanboy D. schrieb:
> Der
> Optimizer entscheidet das anhand seiner Regeln.

Das mag ich nicht, wenn jemand für mich entscheidet.

Arduino Fanboy D. schrieb:
> __attribute__((always_inline)) macht besonders Sinn, wenn man auch bei
> niedriger Optimierungstufe ein inlinig erzwingen muss/möchte

Nein, das macht gerade mit Q3 viel Sinn. Sonst macht Compiler wie er 
mag: mal so mal so. Ich möchte bei bestimmten Funktionen sicher sein, 
daß ich zu drei oder vier einfachen Befehlen nicht noch eine Menge von 
push und pop bekomme.

Interessant dabei: oft bekommt man mit __attribute__((always_inline)) 
nicht nur schneller sondern auch kleinere Code. Ein Beispiel: um eine 
Funktion mit mehreren Argumenten zu rufen, bringt Compiler die zuerst in 
R24-R25- usw, dann folgt call. Wenn man inline erzwingt, bringt Compiler 
diese Argumenten gleich in Register, wo ausgeführt wird. Somit ist Leib 
der Funktion nicht nur wegen fehlenden push und pop kürzer, sondern auch 
durch nicht mehr notwendigen mov zwischen Registern. So kommt oft vor, 
daß Gesamtcode auch bei 10x Verwendung mit 
__attribute__((always_inline)) kürzer ist, als Leib der Funktion + 10x 
ldi,ldi,ldi,ldi... und call dazu.

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> Das mag ich nicht, wenn jemand für mich entscheidet.
Immerhin ist der Optimierer über Kommandozeilenparameter und pragmas 
vielfältig konfigurierbar.

Maxim B. schrieb:
> Benutzt du diese Einstellung???
Selten.

z.B. mal kurz wenn ich ein unerklärliches Fehlverhalten vorfinde.
Wenn es dann mit -O0 funktioniert, ist die Wahrscheinlichkeit groß, dass 
ich versehentlich ein UB eingebaut habe. Zudem lässt sich der erzeugte 
ASM Code leichter lesen, da einen klareren Bezug zum Quellcode hat.

In der Regel macht der Optimierer sein Ding recht gut. Klar, gibts auch 
mal Irritationen, wenn man einen Scheifenzähler Grenzwert erhöht, oder 
bei einem switch einen Fall hinzufügt. Und der Optimierer darum die 
Schleifen eben nicht mehr ausrollt, oder das switch/case in eine 
Sprungtabelle stopfen kann.
Aber mit inline hat das alles wenig zu tun.


Ansonsten:
Takte zählen und Extrawürste backen, nur wenn unbedingt nötig. Meist 
interessiert mich das Null,Null.

von Maxim B. (max182)


Lesenswert?

Arduino Fanboy D. schrieb:
> Takte zählen und Extrawürste backen, nur wenn unbedingt nötig.

Wenn Unterschied schon z.B. 500 Bytes ist, dann muß man manchmal mit dem 
Kopf denken :)

von Einer K. (Gast)


Lesenswert?

Maxim B. schrieb:
> dann muß man manchmal mit dem
> Kopf denken :)

Wie gesagt...
> Wenn es nötig ist.

Ansonsten wird denken auch gerne mal überbewertet.

von Maxim B. (max182)


Lesenswert?

Ein Beispiel:
1
static inline void spi_intern_outadr(u8 adr){
2
3
  if(adr & (1<<0)){
4
    SPI_INTERN_A0_PORT |= (1<<SPI_INTERN_A0);
5
  }else{
6
    SPI_INTERN_A0_PORT &= ~(1<<SPI_INTERN_A0);
7
  }
8
  if(adr & (1<<1)){
9
    SPI_INTERN_A1_PORT |= (1<<SPI_INTERN_A1);
10
  }else{
11
    SPI_INTERN_A1_PORT &= ~(1<<SPI_INTERN_A1);
12
  }
13
  if(adr & (1<<2)){
14
    SPI_INTERN_A2_PORT |= (1<<SPI_INTERN_A2);
15
  }else{
16
    SPI_INTERN_A2_PORT &= ~(1<<SPI_INTERN_A2);
17
  }
18
}
 mit Q3 macht Compiler wie eine gewöhnliche Funktion, mit viel Code, mit 
bedingten Sprüngen und push-pop. Dabei ist jeder call auch ziemlich 
groß, 10 Bytes. Erst mit static _inline_ void spi_intern_outadr(u8 
adr) __attribute__((_always_inline_));
 wird das ordentlich gemacht, mit nur drei cbi oder sbi, je nach der 
Lage. D.h. 6 Bytes pro Aufruf. Viel schneller und viel kleiner. 
Unterschied ist zu gravierend, um zu ignorieren.

von Einer K. (Gast)


Lesenswert?

Kann ich nicht beurteilen, zu sehr aus dem Kontext gerissen.
Aber wenn das für dich richtig ist, dann gut, was soll ich sonst dazu 
sagen?

PS:
Ich habe mich erinnert, du beziehst dich auf diesen Thread:
Beitrag "Lokale Variable statt static, aber optimiert. Wie?"

Das dortige Problem würde ich sicherlich gänzlich anders angehen, wenn 
es sich mir stellen würde...

In der Arduino Welt haben wir dafür:
https://www.arduino.cc/en/Reference/SPISettings
Ob das jetzt effektiver ist?
Vermutlich nicht wirklich.
Aber ein Programm, welches das nutzt ist schnell zusammen gedengelt und 
auch µC Familien übergreifend nutzbar.

von Stefan F. (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Wenn es dann mit -O0 funktioniert, ist die Wahrscheinlichkeit groß, dass
> ich versehentlich ein UB eingebaut habe.

Ja. Ist mir zum Glück noch nie passiert. Ich schau mir allerdings auch 
die Warnungen des Compilers und der IDE an.

von RBK (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:
> Aber in der Regel ist es mittlerweile egal, ob du Funktionen als static
> oder inline deklarierst. Oder auch beides.
> Das eine impliziert das andere.

Was genau bedeutet denn eine Inline-Funktion?

von Einer K. (Gast)


Lesenswert?

RBK schrieb:
> Arduino Fanboy D. schrieb:
>> Aber in der Regel ist es mittlerweile egal, ob du Funktionen als static
>> oder inline deklarierst. Oder auch beides.
>> Das eine impliziert das andere.
>
> Was genau bedeutet denn eine Inline-Funktion?
????

Was ich weiß, sachte ich schon!

Arduino Fanboy D. schrieb:
> Das steht bei (fast?) allen modernen Kompilern dabei, das ein einfaches
> inline nur eine Empfehlung ist.
> Keinesfalls verpflichtend.
> Und z.B. bei gcc -O0 gar nicht zur Geltung kommt.

Früher war alles besser!
Sogar die Zukunft, und das inline Attribut hatte damals noch eine 
garantierte Wirkung.


---------
Nachtrag (nach etwas überlegen):
> Was genau bedeutet denn eine Inline-Funktion?
Eine inline Funktion ist einen inline Funktion, wenn der Kompiler sie 
inline eingebunden hat. Was recht logisch und zwangsläufig zur Folge 
hat, dass der Linker sie nicht auflösen muss, wenn man sie als solche 
deklariert hat.

von Einer K. (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Ja. Ist mir zum Glück noch nie passiert. Ich schau mir allerdings auch
> die Warnungen des Compilers und der IDE an.
Naja..
Der Compiler meldet nicht alles, was in einen UB führt.

von Maxim B. (max182)


Lesenswert?

RBK schrieb:
> Was genau bedeutet denn eine Inline-Funktion?

So etwa wie Macros, nur anders geschrieben.

von Wie wahr (Gast)


Lesenswert?

Maxim B. schrieb:
> So etwa wie Macros, nur anders geschrieben.

Genau
https://de.wikipedia.org/wiki/Makro

von c-hater (Gast)


Lesenswert?

Arduino Fanboy D. schrieb:

> Eine inline Funktion ist einen inline Funktion, wenn der Kompiler sie
> inline eingebunden hat. Was recht logisch und zwangsläufig zur Folge
> hat, dass der Linker sie nicht auflösen muss, wenn man sie als solche
> deklariert hat.

Das stimmt zwar, ist aber nur ein Nebeneffekt, der sich aus der Logik 
der Sache ergibt.

Was inline wirklich tut (wenn es das tut, was man erwarten könnte), ist:

Verzichte auf den Callframe! Und bei "Hochsprachen" (C/C++ sein hier mal 
mitgerechnet) ggf. auch noch: Und auf weiteres sinnloses Gewichse, was 
nur aus den intelligenzmäßig etwas unterbelichteten Makro-Bausteinen 
resultiert, die einen C/C++-Compiler im Kern ausmachen...

Im Endeffekt wird also der der Nutzcode der inline-Funktion direkt in 
der Funktion generiert, die diese Inline-Funktion aufruft.

Von diesem Nutzcode gibt es also für jede aufrufende Code-Instanz eine 
eigene Inkarnation im Programmspeicher. Das ist (fast) immer schlecht 
für eine Optimierung auf minimale Codegröße, aber im Gegenzug oft sehr 
gut für eine Optimierung auf Geschwindigkeit.

Das Grundprinzip ist simpel. Verdammenswürdig ist nur, dass der Compiler 
sich erfrecht, die letzte Entscheidung selber treffen zu wollen. Das 
steht ihm nicht zu, er ist nur ein Werkzeug. Da könnte ja auch eine 
Kombizange auf die Idee kommen, zu entscheiden, nö, heute ist Montag, da 
mag ich keine Drähte trennen, heute sind nur Flachzangen-Anwendungen 
drin.

Kein Handwerker mit Berufsehre würde so eine Kombizange ernsthaft 
benutzen wollen, das Ding landet natürlich sofort im Müll.

C-Programmierer sind da wohl härter im Nehmen. Die lassen sich von ihrem 
Werkzeug vorschreiben, was besser ist. Auch dann, wenn es nicht wirklich 
besser ist...

von Assembler oder gleich Binärcode schreiben? (Gast)


Lesenswert?

c-hater schrieb:
> C-Programmierer sind da wohl härter im Nehmen.

Ist es nicht eher so, dass gerade C "trust the programmer" als Logo hat?

Die anderen Programmiersprachen trauen dem Programmierer doch nicht mal 
zu Speicher zu reversieren / freigeben.

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> Kein Handwerker mit Berufsehre würde so eine

so eine Sprache benutzen wie du. Ich mag dir gar nicht die Hand geben, 
wer weiß wo die gerade war.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:

> so eine Sprache benutzen wie du.

Welche Passge hat dir denn nicht gefallen? Ich kann da nix verwerfliches 
finden? Hach, verdammt.

Ersetze meinetwegen "Gewichse" durch "Gerödel" oder was immer du für 
sinnlosen, nutzlosen, zeitfressenden Code als angemessenen Bezeichnung 
wählen würdest.

An den Fakten ändert das exakt garnix!

von Stefan F. (Gast)


Lesenswert?

c-hater schrieb:
> ich kann da nix verwerfliches finden?

Das war mir schon klar. Denn in beinahe jedem Beitrag beleidigst du in 
einem großen Rundumschlag Gott und die Welt die sich um dich dreht.

> An den Fakten ändert das exakt garnix!

Das sind keine Fakten, sondern deine seltsamen Meinungen. Du kommst mir 
wie der Geisterfahrer vor, der sich darüber wundert, dass alle anderen 
falsch herum fahren.

von c-hater (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:

>> An den Fakten ändert das exakt garnix!
>
> Das sind keine Fakten

Doch, das sind Fakten. Jeder Compilerbauer wird dir das bestätigen 
können.

Er wird dir vermutlich nur eins nicht bestätigen wollen, dass es nicht 
gut ist, die letzte Entscheidung bezüglich des Inlining dem Compiler 
vorzubehalten...

Auch das ergibt sich aus dem beobachteten Sachverhalt. Jedenfalls für 
jeden, der logisch denken kann...

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.