Hi,
kann jemanden mir sagen warum ist Zeiger auf Funktion überhaupt
verwendet?
was ist das Ziel? kann der Inhalt von diesem Zeiger auslesen?
wenn ich eine Funktion deklariere, die als Argument ein Zeiger auf
Funktion hat. Wie wird überhaupt die Funtion aufgerufen? Was versteckt
sich in diesem Argument?
Einfachstes Beispiel:
Du hast eine generische Sortierfunktion.
Woher weiß jetzt diese Sortierfunktion wie es bewerten soll welches von
2 Objekten in der Reihenfolge zuerst kommt.
Du übergibst der Sortierfunktion einfach einen Zeiger auf eine
Vergleichsfunktion mit 2 'void' zeigern die auf die zu vergleichenden
Objekte zeigen. Die Funktion muss dann je nachdem welches Objekt
'größer' ist -1, 0 oder 1 zurückliefern.
Schau dir qsort() an.
Frager schrieb:> kann jemanden mir sagen warum ist Zeiger auf Funktion überhaupt> verwendet?
Dann, wenn man erst zur Laufzeit (in Abhängigkeit von anderen Daten)
festlegen möchte, welche konkrete Funktion dann später aufgerufen
werden soll.
Frager schrieb:> Hi,> kann jemanden mir sagen warum ist Zeiger auf Funktion überhaupt> verwendet?> was ist das Ziel?
Ein Funktion aufzurufen, die der Aufrufer nicht persönlich kennen muss,
sondern die ihm wer anderer vorgibt.
Karl Heinz Buchegger schrieb:> Ein Funktion aufzurufen, die der Aufrufer nicht persönlich kennen muss,> sondern die ihm wer anderer vorgibt.
Völlig falsch. Die Funktion soll variabel sein.
Kan asta schrieb:> Karl Heinz Buchegger schrieb:>> Ein Funktion aufzurufen, die der Aufrufer nicht persönlich kennen muss,>> sondern die ihm wer anderer vorgibt.>> Völlig falsch. Die Funktion soll variabel sein.
Und wie beißt sich das jetzt mit dem was ich gesagt habe?
Sorry,
Ich habe schon die Frage hier gestellt aber ohne Erfolg.
ich möchte einen Zeiger auf eine Funktion, der mir bei Sortierung eines
Arrays helfen kann. D.h ob ich eine aufsteigende Sortierung oder
absteigerung Sortierung mache.
Die Sortierung selbst ist kein Problem aber ich möchte nur diese mit
einem Zeiger auf Funktion machen. Um zu lernen wie es funktioniert.
1) wenn pArray[0] > pArray[1]-> absteigend
2) wenn pArray[0] < pArray[1]-> aufsteigend
3)Nach meiner Meinung nach, wenn ich die Funktion vBubblesort
aufrufe,dann soll Parameter 1 oder 0 sein
Im debbuger ich sehe nichts interessant.Ich bekomme sogar 2 verschiedene
Adresse von pBubble beim Auruf von (*pBubble)(cArray) und vBubblesort.
uint8_t (*pBubble)(char *pArray);//Pointer of function
uint8_t u8ChoiceBubble(char *pArray);//
void vBubblesort(uint8_t(*pBubble)(char *pArray),char *pArray, uint8_t
u8length);
int main()
{
pBubble = &u8ChoiceBubble;
(*pBubble)(cArray);
vBubblesort(u8ChoiceBubble,cArray, u8LencArray);
// u8InitDirection=u8ChoiceBubble(cArray);
}
uint8_t u8ChoiceBubble(char *pArray)
{
if(pArray[0] < pArray[1])
{
return 1;
}
else
{
return 0;
}
}
void vBubblesort(uint8_t(*pBubble)(char *pArray),char *pArray, uint8_t
u8length)
{
if(pBubble==1)
{
}
if(pBubble==0)
{
}
}
Frager schrieb:> Sorry,> Ich habe schon die Frage hier gestellt aber ohne Erfolg.
Erinnere mich.
Du hast viele Antworten bekommen. Nur leider hast du sie nicht
verstanden.
Die erste (und oberste) Frage ist.
Wozu brauchst du hier einen Zeiger auf eine Funktion?
> Die Sortierung selbst ist kein Problem aber ich möchte nur diese mit> einem Zeiger auf Funktion machen. Um zu lernen wie es funktioniert.> 1) wenn pArray[0] > pArray[1]-> absteigend> 2) wenn pArray[0] < pArray[1]-> aufsteigend
Geh von deinem ursprünglichen Verfahren aus
sorted = false;
while( !sorted ) {
sorted = true;
for( i = 0; i < arraySize - 1; i++ ) {
if( array[i] > array[i+1] ) {
swap( array[i], array[i+1] );
sorted = false;
}
}
}
Dann gehst du her und verschiebst den Vergleich erst mal in eine
Funktion
sorted = false;
while( !sorted ) {
sorted = true;
for( i = 0; i < arraySize - 1; i++ ) {
if( sortOrder( array[i] > array[i+1] ) )
swap( array[i], array[i+1] );
sorted = false;
}
}
}
und anstelle einer fixen Funktion sortOrder tritt dann ein
Funktionspointer
> 3)Nach meiner Meinung nach, wenn ich die Funktion vBubblesort> aufrufe,dann soll Parameter 1 oder 0 sein
Dann bringt dir das ganze nichts.
Denn dann braucht die Funktion keinen Funktionspointer.
> void vBubblesort(uint8_t(*pBubble)(char *pArray),> char *pArray, uint8_t u8length)> {> if(pBubble==1) {> }> if(pBubble==0) {> }> }>> Wenn ich mir das nun so anschaue ... Die untere> fkt macht irgendwie keinen Sinn.
Genau. Der Funktionspointer ist an dieser Stelle völlig sinnlos. Wenn du
der Funktion sowieso mitgeben willst, ob sie aufsteigend oder absteigend
zu sortieren hat, dann brauchst du auch keinen Funktionspointer. Ein
normaler uint8_t würde es auch tun.
void vBubblesort(uint8_t ascending, char *pArray, uint8_t u8length)
{
if( ascending )
vBubbleSortAscending( pArray, length );
else
vBubbleSortDescending( pArray, length );
}
und dazu 2 Sortierroutinen von denen die eine aufsteiegend und die
andere absteigend sortiert.
Frager schrieb:> was ist:>> while( !sorted )
Lies es so wie es da steht. ! ist in C ein "nicht"
Das steht also: Solange (while) nicht (!) sortiert (sorted)
Also: Die übliche C Schreibweise für
while( sorted == FALSE )
oder auch
while( sorted != TRUE )
oder eben
while( !sorted )
(wobei sorted logischerweise eine Variable ist, die boolschen Character
hat, also nur TRUE oder FALSE sein kann)
Edit: Aber ich merke gerade, dass ich da bei dem Codestück nicht
besonders gut auf diesen Teilaspekt geachtet habe. Da sind ein paar
Fehler drinnen (die nichts mit dem Ersatz durch einen Funktionspointer
zu tun haben). Ich hab sie trotzdem korrigiert.
Karl Heinz Buchegger schrieb:> (wobei sorted logischerweise eine Variable ist, die boolschen Character> hat, also nur TRUE oder FALSE sein kann)
was nicht so sein muss, in C kann es jede art von variable sein - sie
muss nur auf 0 vergleichbar sein.
Klaus Wachtler schrieb:> Frager schrieb:>> while( !sorted )>> Das kommt aus dem Indianischen und heißt etwa "lies mal endlich ein> C-Buch"
Da hat der Klaus leider recht.
Wozu wirfst du mit Funktionspoitner um dich, wenn du an den Grundlagen
schon Schwierigkeiten hast.
Erledige doch erst mal deine 'Pflicht', ehe es in die 'Kür' geht.
Funktionspointer sind in C das, was im Eiskunstlauf der doppelte Axel
ist. Du fängst erst damit an, wenn du das erste mal einen Nachmittag auf
der Eisfläche ohne Hinfallen hinter dir hast. Ein ! nicht zuordnen zu
können ist hingegen "Hinfallen nach 10 Sekunden"
hahahawahahaha
Karl Heinz Buchegger schrieb:> Wozu wirfst du mit Funktionspoitner um dich, wenn du an den Grundlagen> schon Schwierigkeiten hast.> Erledige doch erst mal deine 'Pflicht', ehe es in die 'Kür' geht.> Funktionspointer sind in C das, was im Eiskunstlauf der doppelte Axel> ist. Du fängst erst damit an, wenn du das erste mal einen Nachmittag auf> der Eisfläche ohne Hinfallen hinter dir hast.
Da hat Karl schon recht: erst ein C-Buch lesen, dann "bei Problemen"
nachfragen. Allerdings sind Funktionspointer eigentlich auch nur Zeiger;
das mit der doppelten Axel kann ich nicht nachvollziehen.
Peter II schrieb:> Karl Heinz Buchegger schrieb:>> (wobei sorted logischerweise eine Variable ist, die boolschen Character>> hat, also nur TRUE oder FALSE sein kann)>> was nicht so sein muss, in C kann es jede art von variable sein - sie> muss nur auf 0 vergleichbar sein.
Wobei dann allerdings streng genommen
while( sorted == FALSE )
nicht mehr das exakte Gegenteil von
while( sorted != TRUE )
ist. Daher hab ich ja auch von "boolschem Charakter" gesprochen :-)
mann Klaus, bei dir geht aber auch manchmal die Logik durch...
Ich denke mal du meintest dass
while(sorted == FALSE)
nicht das Gleiche ist wie
while (sorted != TRUE)
Ist es nämlich auch nur bei "echten" Boolschen Variablen.
Kan asta schrieb:> das mit der doppelten Axel kann ich nicht nachvollziehen.
Gemeint war:
Ein Lernender benötigt so schnell keine Funktionspointer.
Und wenn er das erste mal darauf stösst und welche einsetzen will, dann
dürfen solche Fragen wie eben die nach dem ! nicht mehr auftauchen.
Da die Frage aber auftaucht, ist die Schlussfolgerung: heb dir das für
später auf. Zum jetzigen Zeitpunkt sind für dich Funktionspointer noch
zu früh.
Ein schönes Beispiel für Funktionszeiger finde ich auch folgendes Modul.
Läuft ein C-Programm nicht auf einem PC sondern in einer non-hosted
Umgebung wo es keine Console gibt, wissen Funktionen wie printf nicht,
wo und wie sie ihre Eingabe abladen sollen.
Will man zum Beispiel ein Programm wie "Hallo Welt"
1
#include<stdio.h>
2
3
intmain(void)
4
{
5
printf("Hallo Welt!\n");
6
7
return0;
8
}
Auf einem Mikrocontroller wie AVR laufen lassen, ist das printf quasi
eine "Frau ohne Unterleib", den man erst bereitstellen muss.
Dazu überschreibt man stdout des Systems mit eigenen Versionsn, die
Zeiger auf die eigenen Ausgabefunktionen erhalten und klinkt sich so
transparent in die Ausgabe ein, d.h. am verwendenden Programm wie
"Hallo Welt" muss nichts geändert werden.
Hier werden die Funktionen/Funktionszeiger als Callback verwendet, und
die Callback-Verwendung von Funktionszeigern dürfte mithin die häufigste
sein.
Das Modul stellt eine Verbindung zwischen stdout, stderr, stdin
einerseits un UART-Routinen andererseits her. Die UART-Routinen selbst
sind nicht in diesem Modul drinne; das Modul stellt lediglich das
"Fräulein vom Amt" dar, das stdio mit UART verstöpselt.
1
#include<stdio.h>
2
#include"uart.h"
3
4
// Provide output and input function of proper prototypes to
5
// feed in FDEV_SETUP_STREAM below.
6
7
staticint
8
myio_putchar(charc,FILE*f)
9
{
10
// We use this function to set up stdio et al.,
11
// thus we do not need f. The following line prevents the
12
// compiler from complaining about the unused parameter f.
13
(void)f;
14
15
// uart_putchar is just a wrapper for the output function,
16
// so here we go for the output of char c in module uart.c:
17
uart_putc(c);
18
19
#ifdef HOST_WINDOWS
20
// For MS-Windows terminal: add "carriage return" after "newline"
21
if(c=='\n')
22
uart_putc('\r');
23
#endif /* HOST_WINDOWS */
24
25
return0;
26
}
27
28
// Wrap uart_getc into proper prototyped function, too
29
30
staticint
31
myio_getchar(FILE*f)
32
{
33
// f is not needed, so once again we give gcc its pacifier
34
(void)f;
35
36
returnuart_getc();
37
}
38
39
// Build up the FILE object for our UART communication
// The following function will be called automatically before main.
45
46
staticvoid__attribute__((constructor,used))
47
myio_setup_stdio(void)
48
{
49
// Initialize UART. For UART mode (8N1) and baudrate see there.
50
uart_init();
51
52
// Let the standard streams point to our UART-stream objcet.
53
stdout=&myio_stream;
54
stdin=&myio_stream;
55
stderr=&myio_stream;
56
}
Schaut man sich das Präcompilat an, dann sieht die Definition von
myio_stream so aus:
1
staticstruct__filemyio_stream=
2
{.put=myio_putchar,
3
.get=myio_getchar,
4
.flags=(0x0001|0x0002),
5
.udata=0,
6
};
myio_setup_stdio wird übrigens als Constructor definiert und vor main
aufgerufen, so daß in main printf et al. voll funktionsfähig sind.
Die Verwendung dieser I/O-Implementierung geschieht durch Hinzulinken
des Moduls. Möchte man eine andere I/O-Implementierung, linkt man
einfach ein anderes, entsprechend angepasstes Modul hinzu, das die
Verdrahtung zu den gewünschten Ein-/Ausgabeprimitiven übernimmt.
Mit welchen Linkereinstellungen und Defines?
Zudem: Das Modul ist geschrieben um gut verständlich zu sein, nicht um
das letzte Byte an Performance rauszuquetschen; dann ist printf eh
obsolet.
Wobei ich sagen muss, dass das in C nicht so toll ist.
In anderen Sprachen geht das weiter und da haben Funktionszeiger auch
richtige Typen. In anderen Sprachen geht man sogar so weit, dass man
einen Funktionsblock so wie eine Variable handhaben kann. Damit kann man
dann schicke Sachen machen.
Andere Anwendungen sind eine Form von Objektorientierung, oder
Callback-Routinen in der ereignissgesteuerten Programmierung.
Wenn Du beispielsweise in Delphi/Lazarus ein Ereignis hast, so wird das
als Funktionszeiger implementiert.
Kan asta schrieb:> #define printf newlib_printf
Damit sind wir dann wirklich bei einer Gemeinheit von C.
Das, was du da versuchst, ist dir verboten. printf ist (wenn man
ein #include <stdio.h> gemacht hat) ein reservierter Bezeichner,
an dem du dich nicht zu vergreifen hast. (*)
Im Übrigen würde dein Ansatz bei der ersten stdio-Funktion, die
nicht printf ist, ins Leere rennen, während bei Johanns Ansatz
wirklich das gesamte stdout ordentlich auf die Callback-Funktion
geleitet wird. Es ist also egal, ob du putchar(), printf(),
fprintf(stdout, ...) oder puts() benutzt, alles kommt da raus, wo
es ankommen soll.
Außerdem musst du das Fahrrad (sprich, das Parsen des Formatstrings
und die Auswertung der Argumente) nicht nochmal erfinden wie in
einer eigenen printf-Implementierung. Das macht die Bibliothek an
genau einer Stelle.
(*) Nur bei einem hosted environment, aber praktisch sind auch
Anwendungen auf Controllern wie dem AVR sinnvollerweise als ein
solches zu betrachten, weil man dann das Optimierungspotenzial des
Compilers besser ausnutzen kann. Ein strlen("Hello") kann der
Compiler dann nämlich durch die Konstante 5 ersetzen, während er
beim Compilieren für ein freestanding environment zur Laufzeit die
Funktion strlen() aufzurufen gezwungen ist.
Christian Berger schrieb:> In anderen Sprachen geht das weiter und da haben Funktionszeiger auch> richtige Typen.
Ach, haben sie denn in C falsche Typen?
Jörg Wunsch schrieb:> wenn man> ein #include <stdio.h> gemacht hat
habe ich nicht.
Jörg Wunsch schrieb:> Im Übrigen würde dein Ansatz bei der ersten stdio-Funktion, die> nicht printf ist, ins Leere rennen
Kann die anderen Funktionen doch genauso umbiegen.
Jörg Wunsch schrieb:> ußerdem musst du das Fahrrad (sprich, das Parsen des Formatstrings> und die Auswertung der Argumente) nicht nochmal erfinden wie in> einer eigenen printf-Implementierung. Das macht die Bibliothek an> genau einer Stelle.
Das Parsen des Formatstrings macht printf selbst, da muss man nix
dazutun.
Es gibt viele Vor- und Nachteile; Johann wollte ein Beispiel, wie es
ohne sein "Modul" geht.
Wie gesagt, nur das Define tuts nicht. Wo kommt denn der Prototyp für
die Funktion her? Und das angesprochene Initialisierungsproblem ist
immer noch da. Entweder muss main verändert werden, oder es wird ein
anderes Modul gebraucht.
Kan asta schrieb:> Das Parsen des Formatstrings macht printf selbst, da muss man nix> dazutun.
Dann verstehe ich überhaupt nicht, wie du das erreichen willst.
Ist aber auch egal. Johann hatte ein Beispiel gebracht, bei dem die
Nutzung von Funktionszeigern zu einem relativ eleganten Design führt.
Wenn du ein Beispiel bringen willst, wie man auch ohne solche Zeiger
in einem ziemlich krückigen Design trotzdem noch eine einigermaßen
vergleichbare Funktionalität erreichen kann, sei dir das unbenommen,
aber dann mach' besser einen anderen Thread auf, denn in diesem hier
geht's um Funktionszeiger.
Ein Beispiel für Funktionspointer ist auch mein Scheduler:
Beitrag "Wartezeiten effektiv (Scheduler)"
Damit kann man die zu verzögernde Funktion ganz einfach über ihren Namen
einfügen.
Peter
ich hab zumindest zu der Frage ganz oben im ersten Beitrag, wozu man
function pointer verwenden kann, ein praktisches Beispiel.
Hab nämlich eine Prozessor-Emulation in C geschrieben. Da kam mir die
Möglichkeit, ein Array von function pointern zu verwenden, gerade recht.
Die emulierten Maschinenbefehle sind entsprechend ihres Byte-Codes in
einem function pointer array angelegt.Zunächst hatte ich es mittels
"switch case" Konstrukt aufgebaut, aber den Code fand ich selber
eigentlich schauderhaft schlecht. Und die Maschinencodes am hinteren
Ende brauchten dann auch länger als die vorne dran. Da empfand ich das
function pointer array als sehr elegante Alternative.
Jörg Wunsch schrieb:> aber praktisch sind auch Anwendungen auf Controllern wie dem AVR> sinnvollerweise als ein solches zu betrachten, weil man dann das> Optimierungspotenzial des Compilers besser ausnutzen kann. Ein> strlen("Hello") kann der Compiler dann nämlich durch die Konstante 5> ersetzen, während er beim Compilieren für ein freestanding environment> zur Laufzeit die Funktion strlen() aufzurufen gezwungen ist.
Mal blöd gefragt: Warum? Ist es einer freestanding-Implementation
explizit verboten, eine Funktion namens strlen() zu haben, die durch
besondere Maßnahmen optimiert ist?
Rolf Magnus schrieb:> Jörg Wunsch schrieb:>> aber praktisch sind auch Anwendungen auf Controllern wie dem AVR>> sinnvollerweise als ein solches zu betrachten, weil man dann das>> Optimierungspotenzial des Compilers besser ausnutzen kann. Ein>> strlen("Hello") kann der Compiler dann nämlich durch die Konstante 5>> ersetzen, während er beim Compilieren für ein freestanding environment>> zur Laufzeit die Funktion strlen() aufzurufen gezwungen ist.>> Mal blöd gefragt: Warum? Ist es einer freestanding-Implementation> explizit verboten, eine Funktion namens strlen() zu haben, die durch> besondere Maßnahmen optimiert ist?
Natürlich kannst du eine optimierte strlen zur Verfügung stellen.
Aber aufgerufen werden muss die Funktion trotzdem, weil in einer
nihct-hosted Umgebung strlen keine besondere Bedeutung hat und der
Compiler keine Annahmen darüber machen darf .
Im von Jörg genannten Beispiel handelt es sich nicht um eine optimierte
Implementierung von strlen, sondern darum, daß der Compiler wissen über
strlen ausnutzt und es erst garnicht zu einem Aufruf von strlen kommt.
Johann L. schrieb:> Natürlich kannst du eine optimierte strlen zur Verfügung stellen.> Aber aufgerufen werden muss die Funktion trotzdem, weil in einer> nihct-hosted Umgebung strlen keine besondere Bedeutung hat und der> Compiler keine Annahmen darüber machen darf .
Für C an sich hat sie dann keine besondere Bedeutung, aber für den
Compiler kann sie die doch trotzdem haben, oder nicht?
> Im von Jörg genannten Beispiel handelt es sich nicht um eine optimierte> Implementierung von strlen,
Das ist mir schon klar, aber das da:
> sondern darum, daß der Compiler wissen über strlen ausnutzt und es erst> garnicht zu einem Aufruf von strlen kommt.
ist das, was ich mit "durch besondere Maßnahmen optimiert" meinte. Die
Funktion ist halt im Compiler eingebaut, und der kann dann verschiedene
Maßnahmen ergreifen, um hier besser optimieren zu können, als es mit
einer normalen Implementation der Funktion möglich wäre. Meine Frage war
nun: Warum sollte er das bei einer freestanding-Implementation nicht
dürfen? Daß es da keine Standardbibliothek und keine Standard-Funktion
namens strlen() gibt, weiß ich, aber das muß ihn doch nicht davon
abhalten, eine eigene Bibliothek mitzuliefern, wo's dann eben auch so
eine Funktion gibt. Und wenn die zum Compiler gehört, kann er auch auch
Annahmen darüber machen.
strlen kann nicht optimiert werden, weil es keine besondere Bedeutung
hat, genauso wie hasenboppes keine besondere Bedeutung hat. Zitat aus
GCC:
http://gcc.gnu.org/onlinedocs/gcc/Standards.html>> The ISO C standard defines (in clause 4) two classes of>> conforming implementation. A conforming hosted implementation>> supports the whole standard including all the library facilities;>> a conforming freestanding implementation is only required to>> provide certain library facilities: those in <float.h>, <limits.h>,>> <stdarg.h>, and <stddef.h>; since AMD1, also those in <iso646.h>;>> since C99, also those in <stdbool.h> and <stdint.h>; and since C11,>> also those in <stdalign.h> and <stdnoreturn.h>.>> In addition, complex types, added in C99, are not required for>> freestanding implementations.
Wie man sieht sind string.h, stdio.h, etc. nicht dabei.
Rolf Magnus schrieb:> Meine Frage war> nun: Warum sollte er das bei einer freestanding-Implementation nicht> dürfen? Daß es da keine Standardbibliothek und keine Standard-Funktion> namens strlen() gibt, weiß ich, aber das muß ihn doch nicht davon> abhalten, eine eigene Bibliothek mitzuliefern, wo's dann eben auch so> eine Funktion gibt. Und wenn die zum Compiler gehört, kann er auch auch> Annahmen darüber machen.
Und woher soll der Compiler wissen, dass auch seine eigene strlen()
tatsächlich benutzt wird? Woher soll er wissen, dass der Code nicht in
einem anderen Modul eine eigene strlen() mit anderen Eigenschaften hat?
Johann L. schrieb:> strlen kann nicht optimiert werden, weil es keine besondere Bedeutung> hat,
Nochmal: Ob sie im Bezug auf die C-Implementierung eine besondere
Bedeutung hat, hat nichts damit zu tun, ob sie für diesen einen
speziellen Compiler eine besondere Bedeutung hat.
> genauso wie hasenboppes keine besondere Bedeutung hat.
Wenn nun der Compiler eine Bibliothek mitliefert, in der es eine
Funktion hasenboppes() gibt, wer verbietet dann dem Compiler, über genau
diese Funktion genau dieser Bibliothek irgendwelche Annahmen zu machen?
Johann L. schrieb:> Wie man sieht sind string.h, stdio.h, etc. nicht dabei.
Da steht aber auch:
>>> a conforming freestanding implementation is only required to>>> provide certain library facilities
Nicht "only allowed", sondern "only required". Es ist ihr also nicht
verboten, auch andere Teile der Library zu implementieren.
Rolf Magnus schrieb:> Wenn nun der Compiler eine Bibliothek mitliefert, in der es eine> Funktion hasenboppes() gibt, wer verbietet dann dem Compiler, über genau> diese Funktion genau dieser Bibliothek irgendwelche Annahmen zu machen?
Wenn im Code die Funktion hasenboppes() aufgerufen wird, kann der
Compiler gar nicht wissen, ob letztlich die von ihm in der Library
angebotene Implementierung benutzt wird, oder eine ganz andere (andere
Lib, oder direkt im Code). Und bei freestanding ist das bei strlen()
genauso.
Rolf Magnus schrieb:> Nicht "only allowed", sondern "only required". Es ist ihr also nicht> verboten, auch andere Teile der Library zu implementieren.
Genau so lese ich diese Passage übrigens auch.
/EDIT:
Was hält dem Compiler eigentlich davon ab festzustellen, dass die
Funktion strlen völlig reentrant ist und das Argument ohnehin konstant
ist und sie deswegen zur Kompilierzeit auszuführen? Ist das im Standard
explizit verboten?
Nico Sch. schrieb:> Was hält dem Compiler eigentlich davon ab festzustellen, dass die> Funktion strlen völlig reentrant ist und das Argument ohnehin konstant> ist und sie deswegen zur Kompilierzeit auszuführen?
Bei hosted passiert doch genau das. Und bei freestanding geht das nicht,
weil ... (ach, keine Lust das jetzt ein drittes Mal zu schreiben)
Stefan Ernst schrieb:> weil ... (ach, keine Lust das jetzt ein drittes Mal zu schreiben)
Wenn er die Funktion im Quelltext vorliegen hat? Beispielsweise, weil
sie böserweise in einem Header definiert ist?
Nico Sch. schrieb:> Wenn er die Funktion im Quelltext vorliegen hat? Beispielsweise, weil> sie böserweise in einem Header definiert ist?
Ich weiß nicht, worauf du damit jetzt hinaus willst? In dem Fall greifen
natürlich alle Optimierungen, die auch für jede beliebige andere
Funktion im Source greifen würde, inklusive Inlining, ersetzen von
Variablen durch Konstanten, etc.
Rolf Magnus schrieb:> Johann L. schrieb:>> strlen kann nicht optimiert werden, weil es keine besondere Bedeutung>> hat,>> Nochmal: Ob sie im Bezug auf die C-Implementierung eine besondere> Bedeutung hat, hat nichts damit zu tun, ob sie für diesen einen> speziellen Compiler eine besondere Bedeutung hat.
Doch; wenn der Compiler eine C-complaint implementation darstellen soll,
schon.
Hier über nicht-standardkonforme Compiler zu reden ist wenig sinnvoll;
die dürfen natürlich alles.
> Johann L. schrieb:>> Wie man sieht sind string.h, stdio.h, etc. nicht dabei.>> Da steht aber auch:>>>>> a conforming freestanding implementation is only required to>>>> provide certain library facilities
Beispiel: va_start, va_arg und va_end aus stdarg.h
> Nicht "only allowed", sondern "only required". Es ist ihr also nicht> verboten, auch andere Teile der Library zu implementieren.Welche Library denn???
Oben ist keine Library/Header aufgezählt, die ein strlen spezifiziert!
Und da strlen damit im Namespace der Anwendung ist und nicht im
Namespace der Implementierung, hat ein Compiler da nix dran
rumzufutscheln und sich eine eigene Semantik aus den Fingern zu saugen —
egal wie plausibel diese für einen Anwender sein mag.
(Ist schon ein bisschen länger her, ich gehe gerade alte Threads durch,
zu denen ich mal was geschrieben hatte.)
Nico Sch. schrieb:> Stefan Ernst schrieb:>> weil ... (ach, keine Lust das jetzt ein drittes Mal zu schreiben)>> Wenn er die Funktion im Quelltext vorliegen hat? Beispielsweise, weil> sie böserweise in einem Header definiert ist?
Du meinst, ein Compiler würde Quellcode verstehen und könnte aus
diesem Quellcode:
ersetzbar ist? Nein, dazu müsste der Compiler ja den Code der
Target-Maschine selbst ablaufen lassen.
Ein Compiler ist eine Maschine, kein Mensch mit Intelligenz.