Forum: PC-Programmierung Funktionszeiger


von helpme91 (Gast)


Lesenswert?

Hallo,

ich habe gerade ein Beispiel, wo ein Pointer auf eine Funktion zeigt und 
diese aufruft, aber ohne einen Funktionszeizeiger zu erzeugen.

Im Beispiel wurde das so gelöst:
1
char* pointer = setValue();
2
3
char* setValue(void){
4
...
5
}

Ich hätte das so gemacht:
1
char* (*pointer)() = NULL;
2
pointer = setValue;
3
pointer();
4
5
char* setValue(void){
6
...
7
}

Ist die erste Variante aus dem Beispiel eine kurze Variante von meiner 
Lösung?

: Verschoben durch Moderator
von Nop (Gast)


Lesenswert?

helpme91 schrieb:

> Ist die erste Variante aus dem Beispiel eine kurze Variante von meiner
> Lösung?

Nein, die tun verschiedene Sachen. Das erste Beispiel hat nichts mit 
einem Funktionszeiger zu tun, sondern die Funktion hat einen char-Zeiger 
als Rückgabetyp.

von M.A. S. (mse2)


Lesenswert?

helpme91 schrieb:
> Im Beispiel wurde das so gelöst:
>
1
> char* pointer = setValue();
2
> 
3
> char* setValue(void){
4
> ...
5
> }
6
>

Ich bin ja nicht der große C-Spezialist, würde aber sagen, dass in 
diesem Beispiel kein Funktionszeiger vorkommt.
Hier wird eine Zeiger auf char etwas zugewiesen, dass die Funktion 
setValue, die weiter unten definiert wird, erzeugt.

von helpme91 (Gast)


Lesenswert?

O.K.,

aber mir is trotzdem noch nicht klar, was hier jetzt genau passiert?
1
char* pointer = setValue();
2
3
char* setValue(void){
4
...
5
}

Die Funktion setValue(void) gibt mir ja schon einen char Zeiger zurück.
Warum gebe ich diesen Rückgabewert in noch einen Zeiger?

von Hoschti (Gast)


Lesenswert?

helpme91 schrieb:
> char* pointer = setValue();

Das kommt davon, wenn man  zwei Sachen gleichzeitig macht. Schreibt man 
diese Code-Zeile so um, wie ich es es früher (tm) gelernt habe, sieht 
das so aus:

char *pointer;
...
pointer = setValue();

In der Schreibweise sollte klarer sein, was geschieht.

von Nop (Gast)


Lesenswert?

helpme91 schrieb:

> Warum gebe ich diesen Rückgabewert in noch einen Zeiger?

Um ihn danach weiterzuverwenden. So wie jeden anderen Rückgabewert jeder 
anderen Funktion, den Du in einer Variablen speicherst.

von helpme91 (Gast)


Lesenswert?

Ah, o.k.,

dann wir hier also wirklich nur der pointer Rückgabewert der setValue() 
- Funktion in einen weiteren pointer geschrieben und dann mit cout 
ausgegeben.

Richtig so?

von Jonas B. (jibi)


Lesenswert?

>char *pointer;

Das ist nicht gut, besser:

char *pointer = null;

>dann wir hier also wirklich nur der pointer Rückgabewert der setValue()
>- Funktion in einen weiteren pointer geschrieben und dann mit cout
>ausgegeben.

"cout" kommt gar nicht vor im Code...
GetValue() wäre irgendwie passender, den kriegst ja einen Wert und setzt 
ja kein. Merke, eine Funktion sollte immer nur das genau das machen, was 
der Name verspricht.

Gruß J

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

helpme91 schrieb:
> dann wir hier also wirklich nur der pointer Rückgabewert der setValue()
> - Funktion in einen weiteren pointer geschrieben

Wieso weiterer Pointer?
An die internen Pointer der Funktion kommst du nicht ran.

Die Funktion hat irgendwas gemacht und das Ergebnis wird 
(zwischen-)gespeichert.

von leo (Gast)


Lesenswert?

Jonas B. schrieb:
> Das ist nicht gut, besser:
>
> char *pointer = null;

Was genau sollte das bringen, wenn eine Zeite weiter die Initialisierung 
auf den endgueltigen Wert erfolgt?

leo

von Hoschti (Gast)


Lesenswert?

Ist nicht unbedingt notwendig ("C" initialisiert - normaler Weise - alle 
Variablen beim Startup erstmal mit null), ist aber sicherer. Wer weiß 
denn schon, ob da nicht in Zukunft noch was dazwischen codiert wird.

von Jonas B. (jibi)


Lesenswert?

>Was genau sollte das bringen, wenn eine Zeite weiter die Initialisierung
>auf den endgueltigen Wert erfolgt?

Robusten Code. Das lernst du auch noch...

von Jonas B. (jibi)


Lesenswert?

>Ist nicht unbedingt notwendig ("C" initialisiert - normaler Weise - alle
>Variablen beim Startup erstmal mit null)

Käse, der kann laut C-Spezifikation überall hinzeigen...

von leo (Gast)


Lesenswert?

Jonas B. schrieb:
> Robusten Code. Das lernst du auch noch...

Hihi, du meintest ueberfluessigen, zuaetzlich zu lesenden Code.

leo

von Jonas B. (jibi)


Lesenswert?

>Hihi, du meintest ueberfluessigen, zuaetzlich zu lesenden Code.

Du stehst doch scheinbar auf zusätzlichen Code ehm ich meine Buchstaben 
;)

Gute Zusammenfassung:
https://cwe.mitre.org/data/definitions/824.html

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

Jonas B. schrieb:
> Robusten Code. Das lernst du auch noch...

Nein. Vermutlich hast Du den Code auch nicht verstanden, der ist in C im 
Block-scope.

Dort ist die ursprüngliche Schreibweise gut und richtig, wenn es so 
gewünscht ist.

Wenn man jedoch erst mit 0 initialisiert, kann kein Tool der Welt mehr 
warnen, wenn man das initialisieren vergisst.

Zudem warnt z.b. lint, dass ein Wert zugewiesen wird, der niemals 
verwendet wird (unnützer Code).

von leo (Gast)


Lesenswert?

Jonas B. schrieb:
> Du stehst doch scheinbar auf zusätzlichen Code ehm ich meine Buchstaben
> ;)

Ein NULL-Pointer Segfault bringt genau nichts - im Gegenteil. Tools wie 
valgrind zeigen dir uninitalsiete Pointer genau. Du machst also leere 
Kilometer nur wegen deiner ?Paranoia?

leo

von Jonas B. (jibi)


Lesenswert?

>Nein. Vermutlich hast Du den Code auch nicht verstanden, der ist in C im
>Block-scope.

Nein du hast es wieder mal nicht verstanden. Ich sehe nur ein 
Global-Scope.

>Dort ist die ursprüngliche Schreibweise gut und richtig, wenn es so
>gewünscht ist.

He? Hörst du dir eigentlich mal selber zu?

>Wenn man jedoch erst mit 0 initialisiert, kann kein Tool der Welt mehr
>warnen, wenn man das initialisieren vergisst.

"null" und 0 ist nicht das Gleiche, der Rest ist voller Schwachsinn.

>Zudem warnt z.b. lint, dass ein Wert zugewiesen wird, der niemals
>verwendet wird (unnützer Code).

Jaja die linter...

von helpme91 (Gast)


Lesenswert?

Kann man bitte einfach meine Frage beantworten?
Es geht hier jetzt nur um das verständnis, danke.

Ja, cout steht jetzt nicht da, wird aber im Beispiel noch gemacht.
Hat jetzt aber mit der eigentlichen Frage nichts zu tun.

helpme91 schrieb:
> dann wird hier also wirklich nur der pointer Rückgabewert der setValue()
> - Funktion in einen weiteren pointer geschrieben und dann mit cout
> ausgegeben.
>
> Richtig so?

von Thomas F. (tommf)


Lesenswert?

Es wäre echt hilfreich, wenn du das Beispiel mal komplett zeigen 
würdest. So sieht man nur folgendes: Die Funktion setValue() gibt einen 
Pointer auf char zurück und dieser wird in einer Variablen vom Typ char* 
(Pointer auf char) abgespeichert.

Was du danach damit machst, und warum eine Funktion mit dem Namne 
setValue einen Pointer zurück gibt und worauf der zeigt, weisst nur du, 
da du uns das Beispiel nicht zeigst.

von leo (Gast)


Lesenswert?

helpme91 schrieb:
> Kann man bitte einfach meine Frage beantworten?

Das wurde doch schon - mehrfach.

leo

von Dirk B. (dirkb2)


Lesenswert?

helpme91 schrieb:
> Kann man bitte einfach meine Frage beantworten?

Wurde schon gemacht (mehrmals)

von A. S. (Gast)


Lesenswert?

helpme91 schrieb:
> Kann man bitte einfach meine Frage beantworten?
> Es geht hier jetzt nur um das verständnis, danke.
Deine Frage aus dem ersten Post ist beantwortet.

Deine Folgefrage bezog sich auf cout.
>
> Ja, cout steht jetzt nicht da, wird aber im Beispiel noch gemacht.
> Hat jetzt aber mit der eigentlichen Frage nichts zu tun.

Dann stelle doch Deine eigentliche Frage.

von A. S. (Gast)


Lesenswert?

Jonas B. schrieb:
>>Nein. Vermutlich hast Du den Code auch nicht verstanden, der ist
> in C im
>>Block-scope.
>
> Nein du hast es wieder mal nicht verstanden. Ich sehe nur ein
> Global-Scope.
In C gibt es die Zeile nicht im Global-Scope.

> "null" und 0 ist nicht das Gleiche, der Rest ist voller Schwachsinn.
In C ist es das gleiche. So wie Raider und Twix. Auch wenn null hier 
netter ist.

>>Zudem warnt z.b. lint, dass ein Wert zugewiesen wird, der niemals
>>verwendet wird (unnützer Code).
>
> Jaja die linter...
Oder irgendein anderes Tool, dass Warnungen ausspuckt.

von Jonas B. (jibi)


Lesenswert?

>> "null" und 0 ist nicht das Gleiche, der Rest ist voller Schwachsinn.
>In C ist es das gleiche. So wie Raider und Twix. Auch wenn null hier
>netter ist.

Nein. Du hast ein gefährliches Halbwissen. Nochmal Null ist nicht 0.

https://c-for-dummies.com/blog/?p=177

von Nop (Gast)


Lesenswert?

In vielen Implementierungen wird NULL ganz einfach definiert als 
void-Pointer-cast von 0. Also, NULL ist inhaltlich schon 0, aber nicht 
vom Typ her.

Deswegen braucht man globale Pointer in der Tat nicht mit NULL zu 
initialisieren, weil das die C-Runtime automatisch tut, wenn sie die 
globalen Variablen beim Starten nullt.

von A. S. (Gast)


Lesenswert?

Jonas B. schrieb:
>>> "null" und 0 ist nicht das Gleiche, der Rest ist voller
> Schwachsinn.
>>In C ist es das gleiche. So wie Raider und Twix. Auch wenn null hier
>>netter ist.
>
> Nein. Du hast ein gefährliches Halbwissen. Nochmal Null ist nicht 0.
>
> https://c-for-dummies.com/blog/?p=177

Dann gilt aber auch 0 ist nicht 0. Vor allem ist der physikalisch 
gespeicherte Werte bei int *p=0 erstmal egal.

Ich habe keine Ahnung, wo Du stehst. Darum als Frage: Denkst Du, dass
1
int *p=0;
2
int *p=NULL;
irgend eine Art von Unterschied, Fehlverhalten, UB, IB oder was auch 
immer machen (*)? Falls ja, dann nein. Beide sorgen dafür, dass das 
gleiche in p steht, möglicherweise 4711 oder 0xdeadbeaf.

(*) außer dass für NULL eine approbate Definition included werden muss

von mh (Gast)


Lesenswert?

Nop schrieb:
> In vielen Implementierungen wird NULL ganz einfach definiert als
> void-Pointer-cast von 0. Also, NULL ist inhaltlich schon 0, aber nicht
> vom Typ her.

Das in vielen Implementierungen von C so, weil es vom Standard so (oder 
sehr ähnlich) verlangt wird:
1
6.3.2.3 Pointers
2
3 An integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant.55) If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.
3
4 Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
4
[...]
5
55) The macro NULL is defined in <stddef.h> (and other headers) as a null pointer constant; see 7.17.

von Jonas B. (jibi)


Lesenswert?

1
#include <stdio.h>
2
3
int * bla = NULL;
4
int b = 0;
5
6
int main()
7
{
8
    bla = &b;
9
    
10
    if (bla == b)
11
    {
12
        printf("Gleich");
13
    }
14
    else
15
    {
16
        printf("Nicht Gleich");
17
    }
18
19
}

gibt:

main.c:18:13: warning: comparison between pointer and integer
Nicht Gleich

So und jetzt lernt mal C ihr Pfeifen.

von Nop (Gast)


Lesenswert?

Jonas B. schrieb:

> Unpassendes Beispiel

Da hast Du etwas anderes gezeigt, nämlich daß man eine Pointervariable 
mit dem Inhalt NULL nicht mit einer Integervariable mit dem Inhalt 0 
vergleichen darf. Allerdings kommt es dabei auf den Inhalt überhaupt 
nicht an.
1
#include <stdio.h>
2
int * bla = NULL;
3
4
int main()
5
{   
6
    if (bla == 0)
7
    {
8
        printf("Gleich");
9
    }
10
    else
11
    {
12
        printf("Nicht Gleich");
13
    }
14
}

Das wirft keine Warnungen, auch nicht mit -Wall -Wextra, und es wird 
"gleich" ausgegeben.

von Nop (Gast)


Lesenswert?

Nop schrieb:

> Da hast Du etwas anderes gezeigt, nämlich daß man eine Pointervariable
> mit dem Inhalt ... nicht NULL, sondern einer Adresse.

von MaWin (Gast)


Lesenswert?

NULL == 0, auch wenn das Bitmuster der NULL-Addresse nicht 0 ist.

von mh (Gast)


Lesenswert?

Jonas B. schrieb:
> [...]
>
> gibt:
>
> main.c:18:13: warning: comparison between pointer and integer
> Nicht Gleich
>
> So und jetzt lernt mal C ihr Pfeifen.

Ist dir klar was dein Quelltext bedeutet? Oder anders gefragt: Versuchst 
du uns mit Absicht zu verarschen?

von Rolf M. (rmagnus)


Lesenswert?

Jonas B. schrieb:
>>Nein. Vermutlich hast Du den Code auch nicht verstanden, der ist in C im
>>Block-scope.
>
> Nein du hast es wieder mal nicht verstanden. Ich sehe nur ein
> Global-Scope.

Ich sehe einen Ausschnitt aus einem lokalen Scope, denn auf globalem 
Scope kann man in C Funktionen gar nicht aufrufen und auch keine 
Zuweisungen machen.

>>Wenn man jedoch erst mit 0 initialisiert, kann kein Tool der Welt mehr
>>warnen, wenn man das initialisieren vergisst.
>
> "null" und 0 ist nicht das Gleiche, der Rest ist voller Schwachsinn.

"null" gibt es nicht. Was du meinst, ist wohl NULL. Und das muss nach 
ISO-C entweder 0 oder (void*)0 sein. Und der Rest stimmt. Wenn ich die 
Variable definiere und nicht initialisiere und ihm auch später nix 
zuweise, gibt z.B. gcc eine Warnung aus. Wenn ich den erst mit NULL 
initialisiere, nehme ich dem Compiler die Möglichkeit zu warnen.
Beispiel:
1
#include <stdio.h>
2
3
int main(int argc, char* argv[])
4
{
5
    char* p;
6
    if (argc > 1)
7
    {
8
        p = argv[1];
9
    }
10
    puts(p);
11
    return 0;
12
}
Ausgabe des Compilers:
1
zeiger.c: In function ‘main’:
2
zeiger.c:10:5: warning: ‘p’ may be used uninitialized in this function [-Wmaybe-uninitialized]
3
   10 |     puts(p);
4
      |     ^~~~~~~
Ersetze ich die erste Zeile in main() durch:
1
    char* p = NULL;
dann kommt keine Warnung mehr, obwohl das Problem immer noch vorhanden 
ist.

Jonas B. schrieb:
> So und jetzt lernt mal C ihr Pfeifen.

Für das wackelige Wissen, das du hier zeigst, trittst du ganz schön 
arrogant auf. Warum ist b ein int und nicht ein int*? Wir sprachen doch 
darüber, ob 0 im Zeigerkontext das gleiche ist wie NULL. Ist dir 
vielleicht aufgefallen, dass dieses Problem nicht auftritt, wenn b ein 
Zeiger ist, und du dachtest, es merkt keiner, wenn du das dann so 
hinschreibst?

: Bearbeitet durch User
von MaWin (Gast)


Lesenswert?

Jonas B. schrieb:
> int main()
> {
>     bla = &b;

Damit ist bla nicht mehr NULL und wahrscheinlich auch nicht mehr 0 (je 
nach HW Archiketur).
Was hast du erwartet?

von Jonas B. (jibi)


Lesenswert?

>zeiger.c:10:5: warning: ‘p’ may be used uninitialized in this function 
[->Wmaybe-uninitialized]

maybe heißt vielleicht, das heißt der Compiler ist sich nicht mal selber 
sicher. Außerdem musst du ihn mit dem Extra flag aufrufen 
-Wmaybe-uninitialized.. Der rofl rolf, ich lag mich tot.

von Dirk B. (dirkb2)


Lesenswert?

Jonas B. schrieb:
> maybe heißt vielleicht, das heißt der Compiler ist sich nicht mal selber
> sicher.

Das hängt ja vom Programmlauf ab.
Wird das Programm ohne Argument(e) aufgerufen, wird der if-Zweig nicht 
durchlaufen.

Der Compiler weiß das sehr genau.

von Rolf M. (rmagnus)


Lesenswert?

Jonas B. schrieb:
>>zeiger.c:10:5: warning: ‘p’ may be used uninitialized in this function
> [->Wmaybe-uninitialized]
>
> maybe heißt vielleicht,

Da steht nicht "maybe", sondern "may be". Und das steht da, weil es 
davon abhängt, ob das if() true ergibt oder nicht, und das ist zur 
Compilezeit noch gar nicht bekannt. Es kann also je nach übergebener 
Kommandozeile uninitialisiert sein, oder eben auch nicht.

> Außerdem musst du ihn mit dem Extra flag aufrufen -Wmaybe-uninitialized..

Ich hab dieses Flag nicht angegeben, aber -Wall, in dem das beinhaltet 
ist. Ich compiliere eigentlich immer mindestens mit -Wall -Wextra 
-pedantic und rate auch jedem dazu, das zu tun.

> Der rofl rolf, ich lag mich tot.

Weißt du eigentlich, wie lächerlich du dich gerade machst?

: Bearbeitet durch User
von Dirk B. (dirkb2)


Lesenswert?

Jonas B. schrieb:
> Außerdem musst du ihn mit dem Extra flag aufrufen
> -Wmaybe-uninitialized..

Das ist bei -Wall schon mit drin und dass lassen nur Masochisten weg.

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.