Funktionszeiger

Gast #6606441
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?
#6606444
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.
Gast #6606461
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?
Gast #6606468
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.
#6606546
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
Gast #6606566
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.
Gast #6606596
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).
#6606606
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...
Gast #6606631
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?
#6606637
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.
Gast #6606774
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.
Gast #6606815
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.
Gast #6606934
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.
Gast #6606971
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
Gast #6606984
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.
#6607003
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.
Gast #6607014
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.
#6607147
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?
#6607165
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.
#6607181
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?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren