Saya tidak tahu ini:
int main() {
int (*) (int *) = 5;
return 0;
}
Tugas di atas dikompilasi dengan g ++ c ++ 11. Saya tahu itu int (*) (int *)
adalah penunjuk ke fungsi yang menerima (int *)
argumen sebagai dan mengembalikan int, tapi saya tidak mengerti bagaimana Anda bisa menyamakannya dengan 5. Awalnya saya pikir itu adalah fungsi yang secara konstan mengembalikan 5 (dari pembelajaran saya baru-baru ini di F #, mungkin, haha), lalu saya berpikir, secara singkat, bahwa penunjuk fungsi menunjuk ke lokasi memori 5, tetapi itu tidak berfungsi, jelas, dan begitu juga dengan nilai hex.
Berpikir bahwa itu bisa jadi karena fungsinya mengembalikan int, dan menugaskan int itu ok (entah bagaimana), saya juga mencoba ini:
int * (*) (int *) = my_ptr
where my_ptr
is type int *
, type yang sama dengan function pointer kedua ini, seperti pada kasus pertama dengan type int. Ini tidak dapat dikompilasi. Menetapkan 5, atau nilai int apa pun, bukan my_ptr
, tidak dikompilasi untuk penunjuk fungsi ini juga.
Jadi apa maksud dari tugas itu?
Perbarui 1
Kami mendapat konfirmasi bahwa ini adalah bug, seperti yang ditunjukkan pada jawaban terbaik. Namun, masih belum diketahui apa yang sebenarnya terjadi pada nilai yang Anda tetapkan ke penunjuk fungsi, atau apa yang terjadi dengan penetapan tersebut. Penjelasan (bagus) apa pun tentang itu akan sangat dihargai! Lihat hasil edit di bawah untuk kejelasan lebih lanjut tentang masalah tersebut.
Edit 1
Saya menggunakan gcc versi 4.8.2 (di Ubuntu 4.8.2)
Edit 2
Sebenarnya, menyamakannya dengan apa pun berfungsi pada kompiler saya. Bahkan menyamakannya dengan variabel std :: string, atau nama fungsi yang mengembalikan double, berhasil.
Edit 2.1
Menariknya, menjadikannya penunjuk fungsi ke fungsi apa pun yang mengembalikan tipe data yang bukan penunjuk, akan membiarkannya dikompilasi, seperti
std::string (*) () = 5.6;
Tapi begitu penunjuk fungsi adalah ke fungsi yang mengembalikan beberapa penunjuk, ia tidak dapat dikompilasi, seperti dengan
some_data_type ** (*) () = any_value;
sumber
error: expected identifier or '(' before ')' token
int *x = 5
Anda menamakannyax
. Denganint * (*x) (int *) = 5
itu tidak akan dikompilasi. (meskipun itu akan dikompilasi sebagai kode C).int(*) = 5;
danint(*);
Jawaban:
Ini bug di g ++.
int (*) (int *)
adalah nama tipe.
Di C ++ Anda tidak dapat memiliki deklarasi dengan nama tipe tanpa pengenal.
Jadi ini dikompilasi dengan g ++.
int (*) (int *) = 5;
dan ini mengkompilasi juga:
int (*) (int *);
tetapi keduanya adalah deklarasi yang tidak valid.
EDIT :
TC menyebutkan di komentar bugzilla bug 60680 dengan kasus uji serupa
tetapi belum disetujui. Bug dikonfirmasi di bugzilla.EDIT2 :
Ketika dua deklarasi di atas berada pada lingkup file g ++ dengan benar mengeluarkan diagnostik (gagal mengeluarkan diagnostik pada lingkup blok).
EDIT3 :
Saya telah memeriksanya dan saya dapat mereproduksi masalah tersebut pada rilis terbaru g ++ versi 4 (4.9.2), versi pra-rilis terbaru 5 (5.0.1 20150412) dan versi eksperimental terbaru 6 (6.0.0 20150412).
sumber
error C2059: syntax error : ')'
int (*int_func)(int *);
yang menyatakan penunjuk fungsi bernamaint_func
.int x[5];
dan tidakint[5] x;
Ini bukan C ++ yang valid. Ingatlah bahwa karena kompilator khusus Anda kebetulan mengkompilasi, itu tidak membuatnya valid. Kompiler, seperti semua perangkat lunak yang kompleks, terkadang memiliki bug dan ini tampaknya salah satunya.
Sebaliknya,
clang++
keluhan: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.
Ini adalah perilaku yang diharapkan karena baris yang melanggar bukan C ++ yang valid. Ini dimaksudkan sebagai tugas (karena
=
) tetapi tidak berisi pengenal.sumber
Seperti jawaban lain telah menunjukkan, itu adalah bug itu
mengkompilasi. Perkiraan yang masuk akal dari pernyataan ini yang diharapkan memiliki makna adalah:
Sekarang
proc
adalah pointer-to-function yang mengharapkan alamat5
menjadi alamat dasar dari fungsi yang mengambilint*
dan mengembalikanint
.Pada beberapa mikrokontroler / mikroprosesor
5
mungkin terdapat alamat kode yang valid, dan dimungkinkan untuk menemukan fungsi seperti itu di sana.Pada kebanyakan komputer tujuan umum, halaman pertama memori (alamat
0-1023
untuk halaman 4K) sengaja tidak valid (tidak dipetakan) untuk menangkapnull
akses penunjuk.Jadi, sementara perilaku bergantung pada platform, seseorang dapat mengharapkan kesalahan halaman terjadi saat
*proc
dipanggil (misalnya,(*proc)(&v)
). Sebelum waktu*proc
pemanggilan, tidak ada yang tidak biasa yang terjadi.Kecuali jika Anda menulis penaut dinamis, Anda hampir pasti tidak harus menghitung alamat secara numerik dan menetapkannya ke variabel penunjuk-ke-fungsi.
sumber
/usr/lib/gcc/x86_64-pc-cygwin/4.9.2/cc1plus.exe -da so.cpp
Baris perintah ini menghasilkan banyak file perantara. Yang pertama
so.cpp.170r.expand
,, mengatakan:... 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 } ...
Ini masih belum menjawab apa yang terjadi dengan tepat, tetapi ini harus menjadi langkah ke arah yang benar.
sumber