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?




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*...


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.)


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.