www.mikrocontroller.net

Forum: Compiler & IDEs komplizierte Zeiger Funktionen


Autor: noob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
moin, wollte mal sehen was für Zeiger aufrufe ihr schon gesehen oder 
programmiert habt wo man sagen könnte was zum teufel ist das den. Falls 
geht mit Erklärung.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstell doch mal einen Zeiger auf eine Funktion, welche einen Zeiger auf 
eine Funktion übernimmt (die meinetwegen einen int als Argument bekommt) 
und einen ebensolchen Zeiger zurückliefert. Und das alles machst du ohne 
typedef :-)

(Das wäre zb. eine Funktionszeiger auf eine Funktion die irgendwelche 
Handler registriert)

ohne Gewähr
void (*)(int) registerHandler( void (*arg)( int ) )
{
   ...
}

void foo( int arg )
{
}

int main()
{
  void (*)(int) (*RegisterFnct)( void (*)(int) );

  void (* OldFnct)(int);

  RegisterFnct = registerHandler;
  OldFnct = (*RegisterFnct)( foo );
}

Zum Drüberstreuen hätte ich jetzt gerne noch ein Array aus derartigen 
Funktionspointern und eine Funktion, die ein derartiges Array als 
Argument bekommt

(Machs nicht wirklich! Ohne typedef ist sowas hoffnungslos)

Autor: noob (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
geil :)

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <stdio.h>

struct A
{
  int a;
};

struct B
{
  int b;

  struct A a;
};

int main( void)
{
  struct B b;
  struct A* a = &b.a;
  struct B* b2 = ( struct B*) ((( char*) a) - (( int) &((( struct B*) 
NULL)->a)));

  fprintf( stdout, "B: %p A: %p B2: %p\n", &b, a, b2);

  return 0;
}

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich habe vor vielen Jahren einen kleinen embeddable Compiler gebastelt,
der mathematische Funktionen mit mehreren Argumenten als Textstring
einliest und als 68000-Binärcode ausgibt, der wie eine normale
C-Funktion aufgerufen werden kann. Die Compilerfunktion sieht
vereinfacht etwa so aus:
double (*compiler(const char *source))(double *) {
  unsigned short *code;

  code = malloc(MAX_CODE_SIZE);
  // code generation
  // ...
  return (double (*)(double *))code;
}

Um im gleichen Programm unterschiedliche Compiler-Algorithmen
gegeneinander zu testen, könnte man ein Array mit Pointern auf die
einzelnen Compiler anlegen, so dass diese in einer Schleife der Reihe
nach durchgetestet werden können. Das Array sähe dann so aus:
double (*(*comp_array[])(const char *))(double *) = {
  compiler1, compiler2, compiler3
};

Typedefs fand ich damals noch uncool ;-)

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da reicht oft schon viel weniger aus:
char Zeichenkette[100];
char pZeichenkette;
:
  *pZeichenkette + irgendwo = irgendwas;
// oder
  *(char*)&Zeichenkette[0] + irgendwo = irgendwas;
// viele haben damit schon Probleme:
  Zeichenkette[irgendwo] = irgendwas; // Aufruf mit irgendwo==100   :-o
:

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn es richtig schön sein soll:

http://www.ioccc.org/

Oliver

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
extern int (*foo (int (*a (int))(int,int)))(int (*)(int,int));

Deklariert foo als eine Funktion mit einem Paramater a, welcher ein 
Zeiger auf eine Funktion ist, die 2 ints nimmt und einen 
Funktionspointer zurückliefert, die ihrerseits einen Funktionspointer 
auf eine Funktion liefert, die zwei ints nimmt und einen int 
zurückliefert.

In Mathe würd de man sagen foo ist ein Funktional .


Johann

Autor: Bernhard R. (barnyhh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der OP hat bereits im Titel des Threads das Stichwort geliefert:
kompliziert

Software ist nicht dazu da, um irgendetwas kompliziert auszudrücken. 
Software ist dazu da, um Sachverhalte logisch sauber und 
strukturiert darzustellen.

Das Programmieren ist der letzte - rein handwerkliche - Schritt bei der 
Software-Entwicklung.

Hier hat Kompliziertheit nichts aber auch garnichts zu suchen!

Bernhard

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernhard R. wrote:
> Kompliziertheit
Komplexität?

Die Beispiele oben kann man ja durch typedefs vereinfachen, aber er hat 
eben nach kompliziert gefragt, wie du schon sagtest.
Jetzt mach dir mal nicht in die Hose.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Simon K. wrote:
> Bernhard R. wrote:
>> Kompliziertheit
> Komplexität?

Yep. Kompliziert ist immer relativ.

> Die Beispiele oben kann man ja durch typedefs vereinfachen,

Ich würd sogar sagen: Wenn jemand sowas ohne typedef macht, sollte man 
den Code ausdrucken und ihm den Ausdruck solange um die Ohren dreschen, 
bis er freiwillig auf Knien nach Lourdes pilgert, um Abbitte zu leisten 
:-)

> Jetzt mach dir mal nicht in die Hose.

lol

Autor: Sven P. (haku) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens ist im K&R ein Codefetzen enthalten, der beliebige Typendinger 
verbal umformuliert :-)

Autor: yalu (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Folgendes hat scheinbar nichts mit Pointern zu tun. Bei näherem Hinsehen
ist es aber Pointer pur und stellt eine geniale Möglichkeit dar, zu tief
verschachtelte Klammern übersichtlicher darzustellen. Trotzdem würde ich
diesen Stil nicht zur Nachahmung empfehlen ;-)
#include <stdio.h>

int main(void) {
  static int a[8] = { 3, 7, 5, 2, 1, 6, 4, 0 };
  int i;

  for(i=0; i<8; i++)
    printf("%d\n", i[a][a][a][a][a][a][a][a]);
  return 0;
}

Autor: ... (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
yalu, des raff ich ned :D

wer erklärt ?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das Ganze beruht darauf, dass

    a[i]   dasselbe ist wie   i[a]

(folgt aus der C-Definition wie Array Indizierung über Pointer 
Arithmetik abgewickelt wird:
 Der Compiler formt a[i] sofort um zu *(a+i)   (*)
 und i[a] wird ohne Ansehen der Datentypen umgeformt zu *(i+a)

und so wie Pointer Arithmetik in C definiert ist, sind *(a+i) und *(i+a) 
identische Ausdrücke)

Der Ausdruck

     i[a][a][a][a][a][a][a][a]

ist äquivalent zu

     a[a[a[a[a[a[a[a[i]]]]]]]]

Bsp
 i sei gleich 1

a[1]           ist daher 7
a[a[1]]        ist daher gleich a[7]  oder 0
a[a[a[1]]]     ist daher gleich a[0]  oder 3
a[a[a[a[1]]]]                   a[3]  oder 2
.....
(Jetzt sollte das Prinzip schon klar sein. Der Index auf den zugegriffen 
wird, kommt selbst aus dem Array)


Eine Spielart davon, mit der man Leute verblüffen kann
 for( int i = 10; i >= 0; ++i )
   printf( "%c", i[ "Hallo World" ] );   // ein Integer wird mit einem String indiziert :-)

( ist aber dieselbe Idee.   a[i] <==> i[a] )

(*) Das ist auch der Grund, warum man beim Zugriff über Pointer auch 
Array Syntax benutzen kann. Eigentlich war das wahrscheinlich sogar die 
grundelegende Idee dahinter, dass man das können möchte
   char* a = malloc( 20 );
   a[0] = '\0';

geht deswegen, weil a[0] sofort umgeformt wird zu  *(a+0)  und da a ein 
Pointer ist, ist das jetzt eine legale Operation.

Autor: Michael U. (amiga)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hat jetzt zwar nicht nur mit Zeigern was zu tun, aber:
#include <stdio.h>

main(t,_,a)
char *a;
{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94, -27+t, a
)&&t == 2?_<13?main ( 2, _+1, "%s %d %d\n" ):9:16:t<0?t<-72?main(_,
t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\
,/+#n+,/#;#q#n+,/+k#;*+,/'r:'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\
+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\
l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i;:{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
:t<-50?_==*a?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\
+1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \
i@bK'(q)-[w]*%n+r3#l,{}:\nuwloca-O;m.vpbks,fxntdCeghiry"),a+1);}

http://www.bernd-leitenberger.de/echte-programmierer.shtml
dort ganz nach unten scrollen.

Die monster.exe ist sauber, in der Dos-Box aufrufen, damit man die 
Ausgabe sieht. :-)

Gruß aus Berlin
Michael

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
das Letzte beispiel von Bernd-Leitenberger geht aber nicht. Ich vermute 
mal da fehlt ein wichtiges define - oder selbst mein compiler versteht 
nicht was da sache ist.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh, geht doch. Ist halt kein C++ sonder C.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zur Ursprungsfrage. Die Definition der Funktion signal, wie sie früher 
unter Linux auch in der man-Page stand:
void (*signal(int signum, void (*handler)(int)))(int);

Heute verwendet die man-Page langweilige typedefs, durch die man sofort 
sieht, was das bedeutet.

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]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [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.