wake-up-neo.com

Bedeutung von int (*) (int *) = 5 (oder einem beliebigen ganzzahligen Wert)

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;
87
Konrad Kapp

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.

59
ouah

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.

27
Edward

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.

9
Atsby
/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.

2
Roland Illig