Bagaimana void * a = & a legal?

88

Perhatikan kode C ++ berikut:

void* a = &a;

Mengapa kompilator tidak mengeluh karena menggunakan pengenal yang tidak dideklarasikan?

Juga, apa yang dianggap oleh compiler sebagai variabel a? Apakah ini penunjuk ke objek kosong atau penunjuk ke void*penunjuk?

pengguna2681063
sumber
6
Point of Declaration
Grijesh Chauhan
15
Harus menyebutkan mengapa Anda ingin melakukan ini - untuk mendapatkan penunjuk ke atas tumpukan (dari mana Anda dapat mengutak-atik segala macam hal).
OrangeDog

Jawaban:

95

Ruang lingkup deklarasi variabel di C ++ bisa sangat mengejutkan:

void* a =               &a;
         ^~~~~~~~~~~~~~~~~
          a declared as `void*` from here on

Oleh karena itu, &aadalah void**tetapi karena jenis penunjuk apa pun secara implisit dapat diubah menjadi void*...

Matthieu M.
sumber
Bagaimana saya menetapkan objek yang berguna untuk ini?
user2681063
22
@ user2681063 a = &userfulObject?
Nikos C.14
4
@MarkGarcia: Perhatikan bahwa void *a = a;akan menjadi UB jika dideklarasikan secara lokal, jika tidak maka akan baik-baik saja pada cakupan namespace.
Nawaz
1
@TheodorosChatzigiannakis: Saya percaya begitu, ya.
Matthieu M.
1
Kutipan spesifikasi akan sangat bagus di sini.
Benjamin Gruenbaum
30

Itu setara dengan

void* a;
a = &a;

Oleh karena itu, atelah diumumkan. Jadi adapatkan alamat atertulis dalam a. Jadi ini adalah penunjuk ke penunjuk kosong. (Anda belum mendefinisikan objek apa pun.)

Stasik
sumber
9
Secara teknis, Anda memang mendefinisikan satu objek. aitu sendiri adalah sebuah objek. (Tidak semua objek memiliki tipe yang ditentukan pengguna dalam C ++)
MSalters
1
@ MSalters apa 'objek' yang Anda bicarakan ini? : D
Gusdor
3
@Gusdor Kami hanya bisa berasumsi apa yang ada di luar kehampaan cakrawala acara.
Cole Johnson
Mereka disebut berbeda, namun "efeknya" dalam kasus ini sama
Stasik
Mereka tidak setara secara umum, tetapi dalam skenario ini mereka setara .
Balapan Ringan di Orbit
7

In void* a, adideklarasikan sebagai pointer bukan ke voidtipe tapi ke tipe "any" (kasus khusus). Sebuah alamat (posisi dalam memori) ditetapkan ke a, seperti variabel lain yang dideklarasikan, tentu saja.

Setelah itu, ekspresi &adievaluasi untuk menginisialisasi variabel (juga a, tapi ini tidak relevan) baru saja dideklarasikan. Jenisnya &aadalah "penunjuk ke penunjuk ke jenis apa pun", yang merupakan kasus khusus "penunjuk ke jenis apa pun", sepenuhnya kompatibel dengan jenis a. Ergo, tidak ada pesan penyusun.

Akibat wajar: jangan gunakan void*jika Anda ingin pemeriksaan tipe yang kuat. Apa pun dapat diubah menjadi itu. Justru sebaliknya dalam arah sebaliknya, kecuali untuk void*dirinya sendiri (itu akan menjadi pengecualian yang tidak perlu bahwa suatu tipe tidak kompatibel dengan dirinya sendiri).

Juga, AFAIR ini benar-benar berasal dari C.

Mario Rossi
sumber