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?
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.
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.
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.
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.
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?
>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
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.
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
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.
>Ist nicht unbedingt notwendig ("C" initialisiert - normaler Weise - alle>Variablen beim Startup erstmal mit null)
Käse, der kann laut C-Spezifikation überall hinzeigen...
>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
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).
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
>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...
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?
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.
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.
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.
>> "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
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.
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
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.
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
intmain()
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.
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?
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
intmain(intargc,char*argv[])
4
{
5
char*p;
6
if(argc>1)
7
{
8
p=argv[1];
9
}
10
puts(p);
11
return0;
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?
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?
>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.
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.
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?
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.