Forum: Compiler & IDEs komplizierte Zeiger Funktionen


von noob (Gast)


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.

von Karl H. (kbuchegg)


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
1
void (*)(int) registerHandler( void (*arg)( int ) )
2
{
3
   ...
4
}
5
6
void foo( int arg )
7
{
8
}
9
10
int main()
11
{
12
  void (*)(int) (*RegisterFnct)( void (*)(int) );
13
14
  void (* OldFnct)(int);
15
16
  RegisterFnct = registerHandler;
17
  OldFnct = (*RegisterFnct)( foo );
18
}

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)

von noob (Gast)


Lesenswert?

geil :)

von P. S. (Gast)


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;
}

von yalu (Gast)


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:
1
double (*compiler(const char *source))(double *) {
2
  unsigned short *code;
3
4
  code = malloc(MAX_CODE_SIZE);
5
  // code generation
6
  // ...
7
  return (double (*)(double *))code;
8
}

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:
1
double (*(*comp_array[])(const char *))(double *) = {
2
  compiler1, compiler2, compiler3
3
};

Typedefs fand ich damals noch uncool ;-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Da reicht oft schon viel weniger aus:
1
char Zeichenkette[100];
2
char pZeichenkette;
3
:
4
  *pZeichenkette + irgendwo = irgendwas;
5
// oder
6
  *(char*)&Zeichenkette[0] + irgendwo = irgendwas;
7
// viele haben damit schon Probleme:
8
  Zeichenkette[irgendwo] = irgendwas; // Aufruf mit irgendwo==100   :-o
9
:

von Oliver (Gast)


Lesenswert?

Wenn es richtig schön sein soll:

http://www.ioccc.org/

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

1
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

von Bernhard R. (barnyhh)


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

von Simon K. (simon) Benutzerseite


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.

von Karl H. (kbuchegg)


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

von Sven P. (Gast)


Lesenswert?

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

von yalu (Gast)


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 ;-)
1
#include <stdio.h>
2
3
int main(void) {
4
  static int a[8] = { 3, 7, 5, 2, 1, 6, 4, 0 };
5
  int i;
6
7
  for(i=0; i<8; i++)
8
    printf("%d\n", i[a][a][a][a][a][a][a][a]);
9
  return 0;
10
}

von ... (Gast)


Lesenswert?

yalu, des raff ich ned :D

wer erklärt ?

von Karl H. (kbuchegg)


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
1
 for( int i = 10; i >= 0; ++i )
2
   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
1
   char* a = malloc( 20 );
2
   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.

von Michael U. (amiga)


Lesenswert?

Hallo,

hat jetzt zwar nicht nur mit Zeigern was zu tun, aber:
1
#include <stdio.h>
2
3
main(t,_,a)
4
char *a;
5
{return!0<t?t<3?main(-79,-13,a+main(-87,1-_,
6
main(-86, 0, a+1 )+a)):1,t<_?main(t+1, _, a ):3,main ( -94, -27+t, a
7
)&&t == 2?_<13?main ( 2, _+1, "%s %d %d\n" ):9:16:t<0?t<-72?main(_,
8
t,"@n'+,#'/*{}w+/w#cdnr/+,{}r/*de}+,/*{*+,/w{%+,/w#q#n+,/#{l,+,/n{n+\
9
,/+#n+,/#;#q#n+,/+k#;*+,/'r:'d*'3,}{w+K w'K:'+}e#';dq#'l q#'+d'K#!/\
10
+k#;q#'r}eKK#}w'r}eKK{nl]'/#;#q#n'){)#}w'){){nl]'/+#n';d}rw' i;# ){n\
11
l]!/n{n#'; r{#w'r nc{nl]'/#{l,+'K {rw' iK{;[{nl]'/w#q#\
12
n'wk nw' iwk{KK{nl]!/w{%'l##w#' i;:{nl]'/*{q#'ld;r'}{nlwb!/*de}'c \
13
;;{nl'-{}rw]'/+,}##'*}#nc,',#nw]'/+kd'+e}+;\
14
#'rdq#w! nr'/ ') }+}{rl#'{n' ')# }'+}##(!!/")
15
:t<-50?_==*a?putchar(a[31]):main(-65,_,a+1):main((*a == '/')+t,_,a\
16
+1 ):0<t?main ( 2, 2 , "%s"):*a=='/'||main(0,main(-61,*a, "!ek;dc \
17
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

von Peter (Gast)


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.

von Peter (Gast)


Lesenswert?

oh, geht doch. Ist halt kein C++ sonder C.

von Rolf Magnus (Gast)


Lesenswert?

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

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

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.