Forum: Compiler & IDEs Pointer Arithmetic auf Funktionspointer


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 Nils P. (torus)


Bewertung
0 lesenswert
nicht lesenswert
Kürzlich habe ich gelernt, das GCC eine Extension hat um 
Funktionspointer zu vergleichen.

In der Pointer Arithmetik werden Function-Pointer wie übliche char* 
Pointer behandelt.

Ich fand das höchst bizarr. Fällt einem von euch ein Use-Case dafür ein?

von Thomas (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Warum soll das nicht gehen? Übrigens kennt gcc auch einen unären 
&&-Operator und goto *<ptr auf void>

von Rolf M. (rmagnus)


Bewertung
-2 lesenswert
nicht lesenswert
Thomas schrieb:
> Warum soll das nicht gehen?

ISO C verbietet eigentlich Zeigerarithmetik mit Funktionszeigern.
Auch die Konvertierung zwischen Funktions- und Objektzeigern (inklusive 
void*) ist übrigens eigentlich nicht erlaubt. Außerdem ist 
Zeigerarithmetik nur innerhalb von Arrays erlaubt, und Arrays aus 
Funktionen gibt es nicht.

von Thomas (Gast)


Bewertung
-2 lesenswert
nicht lesenswert
Klar, aber nichts hindert dich, den Funktionspointer in ein unsigned zu 
casten. Wozu auch immer. Und Vergleichen geht mit allem.

von MaWin O. (Gast)


Bewertung
-1 lesenswert
nicht lesenswert
Thomas schrieb:
> aber nichts hindert dich, den Funktionspointer in ein unsigned zu
> casten

Die aliasing rules hindern dich daran.

von PittyJ (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Ma W. schrieb:
> Thomas schrieb:
>> aber nichts hindert dich, den Funktionspointer in ein unsigned zu
>> casten
>
> Die aliasing rules hindern dich daran.

Mein Kollege hat immer einen Text ann der Wand hinter dem Schreibtisch:

Lerne die Regeln - und brich sie.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
4 lesenswert
nicht lesenswert
Die einzig wirklich sinnvolle "Arithmetik", die man mit 
Funktionspointern anstellen kann, ist der Vergleich.

von Bernd K. (prof7bit)


Bewertung
2 lesenswert
nicht lesenswert
Rolf M. schrieb:
> und Arrays aus
> Funktionen gibt es nicht.

Es gibt Arrays aus allem erdenklichen, nur die Phantasie des 
Programmierers setzt dem Grenzen.

von Mikro 7. (mikro77)


Bewertung
0 lesenswert
nicht lesenswert
Nils P. schrieb:
> Ich fand das höchst bizarr. Fällt einem von euch ein Use-Case dafür ein?

Als bizarres Beispiel:

In einer gegebenen Implementierung kann einer Funktion f ein Name mit 
set(f,name) zugordnet werden. Die funktion get(f) liefert diesen Namen 
zurück.

Die aktuelle Implementierung von get() durchsucht alle Tupel (f,name) in 
O(n).

Es wird eine schneller Implementierung benötigt und der Compiler 
unterstützt die Erweiterung für einen "<" Operator. Dann könnte man 
bspw. eine B-Baum für eine schnellere Implementierung nutzen.

von Nils P. (torus)


Bewertung
0 lesenswert
nicht lesenswert
Mirko77,

vielen Dank. Du hast recht und so bizarr ist es gar nicht. Eine Map 
Datenstruktur von was-auch-immer auf Funktionspointern macht Sinn, und 
ohne Vergleichsoperator ist da nichts zu machen.

Danke!

von Dumdi D. (dumdidum)


Bewertung
0 lesenswert
nicht lesenswert
PittyJ schrieb:
> Lerne die Regeln - und brich sie.

Ueblicherweise ein guter Spruch, aber nicht bei C seitdem die 
Grammatikanwaelte uebernommen haben.

Rolf M. schrieb:
> Arrays aus Funktionen gibt es nicht.

Echt nicht? Aber Arrazys aus Funktionspointern schon, oder?

von Yalu X. (yalu) (Moderator)


Bewertung
0 lesenswert
nicht lesenswert
Dumdi D. schrieb:
> Rolf M. schrieb:
>> Arrays aus Funktionen gibt es nicht.
>
> Echt nicht? Aber Arrazys aus Funktionspointern schon, oder?

Ja, aber eine Funktion und ein Zeiger auf eine Funktion sind eben nicht
dasselbe:

1
typedef void func(void);  // Funktionstyp                -> ok
2
3
func *funcptrarr[3];      // Array von Funktionszeigern  -> ok
4
func  funcarr   [3];      // Array von Funktionen        -> Fehler

Fehlermeldung beim GCC:

1
error: declaration of ‘funcarr’ as array of functions

von Jim M. (turboj)


Bewertung
-2 lesenswert
nicht lesenswert
Mikro 7. schrieb:
> Die aktuelle Implementierung von get() durchsucht alle Tupel (f,name) in
> O(n).

Für sowas gibts Hash-Funktionen und Hash Maps. Damit bekommt man die 
Zugriffszeit auf O(1).

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Bernd K. schrieb:
> Rolf M. schrieb:
>> und Arrays aus
>> Funktionen gibt es nicht.
>
> Es gibt Arrays aus allem erdenklichen,

In C nicht.

> nur die Phantasie des Programmierers setzt dem Grenzen.

Manchmal auch die Logik.

Dumdi D. schrieb:
> PittyJ schrieb:
>> Lerne die Regeln - und brich sie.
>
> Ueblicherweise ein guter Spruch, aber nicht bei C seitdem die
> Grammatikanwaelte uebernommen haben.

Das hat weder speziell mit C, noch mit "Grammatikanwälten" zu tun. In 
der Programmierung ist es eigentlich nie eine gute Idee, an den Regeln 
der verwendeten Sprache vorbei zu programmieren. Deshalb ist es bei 
neueren Sprachen oft so, dass das gar nicht mehr möglich ist. C ist da 
sehr "liberal" und markiert solche Sachen nur als "undefined behaviour". 
In z.B. Java würdest du gleich einen Fehler vom Compiler oder zumindest 
eine Exception bekommen.

> Rolf M. schrieb:
>> Arrays aus Funktionen gibt es nicht.
>
> Echt nicht?

Ja, echt nicht.

> Aber Arrazys aus Funktionspointern schon, oder?

Ja, die gibt es. Zeiger (egal worauf) sind Objekte, Funktionen sind 
keine Objekte.

von c-hater (Gast)


Bewertung
-9 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:

> Die einzig wirklich sinnvolle "Arithmetik", die man mit
> Funktionspointern anstellen kann, ist der Vergleich.

Ganz klares NEIN.

Nur ein Beispiel: Funktionen für bestimmte Kombinationen von Bits 
irgendwelcher Eingangswerte zu wählen. Die weitaus schnellste Methode 
dafür ist, diese Funktionen über eine Tabelle von Funktionszeigern 
verfügbar zu machen und den Entry in diese Tabelle aus den Eingangsdaten 
zu BERECHNEN (naja: Shift entsprechend der Breite eine 
Funktionszeigers und Addition der Basisadresse der Tabelle, dann 
indirekter Unterprogrammaufruf)

Du hast einfach wirklich keine Ahnung von garnix. Wer zum Teufel hat 
dich eigentlich zum Moderator gemacht?

von Volker B. (Firma: L-E-A) (vobs)


Bewertung
1 lesenswert
nicht lesenswert
c-hater schrieb:

> Nur ein Beispiel: Funktionen für bestimmte Kombinationen von Bits
> irgendwelcher Eingangswerte zu wählen. Die weitaus schnellste Methode
> dafür ist, diese Funktionen über eine Tabelle von Funktionszeigern
> verfügbar zu machen und den Entry in diese Tabelle aus den Eingangsdaten
> zu BERECHNEN (naja: Shift entsprechend der Breite eine
> Funktionszeigers und Addition der Basisadresse der Tabelle, dann
> indirekter Unterprogrammaufruf)

Au weia, was für ein Eigentor! Was hat denn die Berechnung eines 
Tabellenindex' mit Pointerarithmetik zu tun?

Naja, da war der Name des lieben Kollegen mal wieder Programm... :-(

Grüßle
Volker

von Rolf M. (rmagnus)


Bewertung
1 lesenswert
nicht lesenswert
c-hater schrieb:
> Du hast einfach wirklich keine Ahnung von garnix.

Wie üblich mal wieder mit der Beleidigungs-Keule selbst ins Aus 
navigiert. Ärgerlich ist, dass du darüber hinaus leider nicht einmal 
verstanden hast, worum es überhaupt geht…

c-hater schrieb:
> Die weitaus schnellste Methode dafür ist, diese Funktionen über eine
> Tabelle von Funktionszeigern verfügbar zu machen und den Entry in diese
> Tabelle aus den Eingangsdaten zu BERECHNEN (naja: Shift entsprechend der
> Breite eine Funktionszeigers und Addition der Basisadresse der Tabelle,
> dann indirekter Unterprogrammaufruf)

Sehr schön, und wo hast du jetzt mit dem Funktionszeiger gerechnet? Denn 
darum ging es. Nicht die Berechnung eines Index in einer Tabelle, 
sondern Arithmetik mit der Funktions-Adresse, die im Zeiger drin steht.

von (prx) A. K. (prx)


Bewertung
0 lesenswert
nicht lesenswert
"Arithmetik" ist ein grosses Wort für Vergleich auf Gleichheit. Zumal 
nicht auf jeder Plattform ein einfacher bitweiser Vergleich ausreicht. 
Bei real mode x86 beispielsweise nicht, wenn man es genau nimmt.

NB: Diese Plattform illustriert auch, weshalb Vergleich und Arithmetik 
von Pointern auf verschiedene Arrays unzulässig sind, und zu bizarren 
Ergebnissen führen können. Soviel zum Brechen von Regeln.

: Bearbeitet durch User
von Markus F. (mfro)


Bewertung
0 lesenswert
nicht lesenswert
Ein Funktionszeiger (*f)() ist ein Zeiger auf die erste Instruktion 
einer Funktion.

Was soll (z.B.) (*f)() + 5 sein? Ein Zeiger auf die fünfte Instruktion, 
oder was?

von Rolf M. (rmagnus)


Bewertung
0 lesenswert
nicht lesenswert
Markus F. schrieb:
> Ein Funktionszeiger (*f)() ist ein Zeiger auf die erste Instruktion
> einer Funktion.

Auf C-Ebene gibt's kein Konzept von Instruktionen.

> Was soll (z.B.) (*f)() + 5 sein? Ein Zeiger auf die fünfte Instruktion,
> oder was?

Höchstens ein Zeiger auf die fünfte Funktion aus einem Array aus 
Funktionen. Aber Arrays aus Funktionen gibt es eben nicht, unter anderem 
da man ja nicht sicherstellen kann, dass alle Funktionen exakt gleich 
groß sind, was aber Voraussetzung für ein Array ist. Der Nutzen wäre 
auch eher begrenzt. Da nimmt man dann lieber ein Array aus 
Funktionszeigern.

von Rufus Τ. F. (rufus) (Moderator) Benutzerseite


Bewertung
6 lesenswert
nicht lesenswert
c-hater schrieb:
> Du hast einfach wirklich keine Ahnung von garnix.

Ich biete Dir hiermit an, Deinen Beitrag zu löschen, denn damit hast Du 
Dich wirklich in besonderer Art und Weise blamiert. So heftig hast Du 
das bislang noch nicht geschafft.

Ich habe auch nichts dagegen, das für die Nachwelt zu erhalten, denn 
dann können auch andere Forennutzer erkennen, wie sehr von Ahnung und 
Kenntnis Deine Beiträge nur so triefen.

Du kannst auch gerne versuchen, den Fehler wiedergutzumachen und zu 
erklären, was Du da verbockt hast und wo Dein Fehler liegt.

Wie Du mit dem persönlichen Teil umgehst, was Umgangsformen, 
Beleidigungen etc. angeht, überlasse ich auch in Gänze Dir.

Deine Entscheidung.

von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Mikro 7. schrieb:
> In einer gegebenen Implementierung kann einer Funktion f ein Name mit
> set(f,name) zugordnet werden. Die funktion get(f) liefert diesen Namen
> zurück.

Ich wüßte jetzt nicht, wozu man sowas brauchen könnte.
Auf Quelltext-Ebene interessiert mich die Funktionsadresse schlichtweg 
nicht. Ich schreibe immer nur den Namen hin und der Linker kümmert sich 
dann um die Auflösung.

von Frank M. (ukw) (Moderator) Benutzerseite


Bewertung
1 lesenswert
nicht lesenswert
Rufus Τ. F. schrieb:
> c-hater schrieb:
>> Du hast einfach wirklich keine Ahnung von garnix.
>
> Ich biete Dir hiermit an, Deinen Beitrag zu löschen, denn damit hast Du
> Dich wirklich in besonderer Art und Weise blamiert. So heftig hast Du
> das bislang noch nicht geschafft.

Lass das ruhig der Nachwelt erhalten. Die C-Hasser, die überhaupt keinen 
Schimmer haben, aber unbedingt meinen, mitreden zu müssen, sind mir die 
liebsten. Ich habe mir auf seinen Beitrag mal ein Lesezeichen gesetzt. 
Wenn hier im Forum Signaturen üblich wären, hätte ich das direkt mal 
"gesiggt" :-)

: Bearbeitet durch Moderator
von Peter D. (peda)


Bewertung
0 lesenswert
nicht lesenswert
Mikro 7. schrieb:
> Als bizarres Beispiel:
>
> In einer gegebenen Implementierung kann einer Funktion f ein Name mit
> set(f,name) zugordnet werden. Die funktion get(f) liefert diesen Namen
> zurück.

Das ist wirklich bizarr, der Name ist doch die Adresse, d.h. der Linker 
übersetzt alle Namen zu Adressen. Zur Laufzeit gibt es also keine Namen 
mehr im Code. Es ist daher keine Funktion möglich, die den Namen zurück 
liefert.

Man kann bestenfalls ein zusätzliches String-Array anlegen, das Namen 
enthält. Ob diese dann aber gleich den Funktionsnamen sind, liegt im 
Ermessen des Programmierers.

von (prx) A. K. (prx)


Bewertung
0 lesenswert
nicht lesenswert
Peter D. schrieb:
> Es ist daher keine Funktion möglich, die den Namen zurück liefert.

Beim Mikrocontroller nicht. Bei Programmen unter den üblichen 
Betriebssystemen kann das möglich sein, wenn die entsprechende 
Debug-Info im Image vorhanden ist.

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.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

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