Ich kann das nicht herausfinden:
int main() {
int (*) (int *) = 5;
return 0;
}
Die obige Anweisung kompiliert mit g ++ c ++ 11. Ich weiß, dass int (*) (int *)
ein Zeiger auf eine Funktion ist, die ein (int *)
Als Argument akzeptiert und ein int zurückgibt, aber ich verstehe nicht, wie Sie es mit 5 gleichsetzen können. Zuerst habe ich es mir gedacht ist eine Funktion, die konstant 5 zurückgibt (nach meinem letzten Lernen in F #, wahrscheinlich, haha), dann dachte ich kurz, dass der Funktionszeiger auf Speicherplatz 5 zeigt, aber das funktioniert nicht, klar, und hexadezimale Werte auch nicht.
In der Annahme, dass dies daran liegen könnte, dass die Funktion ein int zurückgibt und die Zuweisung eines int (irgendwie) in Ordnung ist, habe ich auch Folgendes versucht:
int * (*) (int *) = my_ptr
wobei my_ptr
vom Typ int *
ist, derselbe Typ wie dieser zweite Funktionszeiger, wie im ersten Fall mit dem Typ int. Dies wird nicht kompiliert. Die Zuweisung von 5 oder eines beliebigen int-Werts anstelle von my_ptr
Wird auch für diesen Funktionszeiger nicht kompiliert.
Was bedeutet die Zuordnung?
pdate 1
Wir haben die Bestätigung, dass es sich um einen Fehler handelt, wie in der besten Antwort gezeigt. Es ist jedoch immer noch nicht bekannt, was tatsächlich mit dem Wert passiert , den Sie dem Funktionszeiger zuweisen, oder was mit der Zuweisung passiert. Für (gute) Erklärungen hierzu wäre ich sehr dankbar! Weitere Informationen zum Problem finden Sie in den nachstehenden Abschnitten.
Edit 1
Ich benutze gcc Version 4.8.2 (in Ubuntu 4.8.2)
Edit 2
Das Gleichsetzen mit irgendetwas funktioniert auf meinem Compiler. Auch das Gleichsetzen mit einer std :: string-Variablen oder einem Funktionsnamen, der ein double zurückgibt, funktioniert.
Edit 2.1
Interessanterweise lässt es sich kompilieren, wenn es zu einem Funktionszeiger auf eine Funktion gemacht wird, die einen Datentyp zurückgibt, der kein Zeiger ist, wie z
std::string (*) () = 5.6;
Sobald der Funktionszeiger jedoch auf eine Funktion verweist, die einen Zeiger zurückgibt, wird er nicht kompiliert, z. B. mit
some_data_type ** (*) () = any_value;
Es ist ein Fehler in g ++.
int (*) (int *)
ist ein Typname.
In C++ können Sie keine Deklaration mit einem Typnamen ohne Bezeichner haben.
Das kompiliert also mit g ++.
int (*) (int *) = 5;
und das kompiliert auch:
int (*) (int *);
aber sie sind beide ungültige Erklärungen.
[~ # ~] edit [~ # ~] :
T.C. erwähnt in den Kommentaren Bugzilla Bug 6068 mit einem ähnlichen Testfall aber es wurde noch nicht genehmigt. Der Fehler ist in Bugzilla bestätigt.
EDIT2 :
Wenn sich die beiden obigen Deklarationen im Dateibereich befinden, gibt g ++ eine Diagnose korrekt aus (die Diagnose kann nicht im Blockbereich ausgegeben werden).
EDIT3 :
Ich habe das Problem in der neuesten Version von g ++ Version 4 (4.9.2), der neuesten Vorabversion 5 (5.0.1 20150412) und der neuesten experimentellen Version 6 (6.0.0 20150412) überprüft und kann es reproduzieren.
Es ist kein gültiges C++. Denken Sie daran, dass Ihr bestimmter Compiler beim Kompilieren nicht gültig ist. Compiler haben, wie jede komplexe Software, manchmal Fehler und dies scheint einer zu sein.
Im Gegensatz clang++
beschwert sich:
funnycast.cpp:3:11: error: expected expression
int (*) (int *) = 5;
^
funnycast.cpp:3:18: error: expected '(' for function-style cast or type construction
int (*) (int *) = 5;
~~~ ^
funnycast.cpp:3:19: error: expected expression
int (*) (int *) = 5;
^
3 errors generated.
Dies ist das erwartete Verhalten, da die betreffende Zeile kein gültiges C++ ist. Es gibt vor, eine Aufgabe zu sein (wegen der =
) enthält aber keinen Bezeichner.
Wie andere Antworten gezeigt haben, ist dies ein Fehler
int (*) (int *) = 5;
kompiliert. Eine sinnvolle Annäherung an diese Aussage, von der erwartet wird, dass sie eine Bedeutung hat, ist:
int (*proc)(int*) = (int (*)(int*))(5);
Nun ist proc
ein Zeiger auf eine Funktion, der erwartet, dass die Adresse 5
Die Basisadresse einer Funktion ist, die einen int*
Annimmt und einen int
zurückgibt. .
Bei einigen Mikrocontrollern/Mikroprozessoren kann 5
Eine gültige Codeadresse sein und es kann möglich sein, eine solche Funktion dort zu lokalisieren.
Auf den meisten Universalcomputern ist die erste Seite des Speichers (Adressen 0-1023
Für 4K-Seiten) absichtlich ungültig (nicht zugeordnet), um null
Zeigerzugriffe abzufangen.
Während das Verhalten von der Plattform abhängt, kann man daher vernünftigerweise erwarten, dass ein Seitenfehler auftritt, wenn *proc
Aufgerufen wird (z. B. (*proc)(&v)
). Vor dem Zeitpunkt, zu dem *proc
Aufgerufen wird, passiert nichts Ungewöhnliches.
Sofern Sie keinen dynamischen Linker schreiben, sollten Sie Adressen mit ziemlicher Sicherheit nicht numerisch berechnen und Zeigervariablen zuweisen.
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp
Diese Befehlszeile generiert viele Zwischendateien. Der erste von ihnen, so.cpp.170r.expand
, sagt:
...
int main() ()
{
int D.2229;
int _1;
;; basic block 2, loop depth 0
;; pred: ENTRY
_1 = 0;
;; succ: 3
;; basic block 3, loop depth 0
;; pred: 2
<L0>:
return _1;
;; succ: EXIT
}
...
Dies antwortet immer noch nicht, was genau passiert, aber es sollte ein Schritt in die richtige Richtung sein.