Pertanyaan Bagaimana struktur ini memiliki sizeof == 0?


Ada posting lama yang meminta konstruksi untuk yang sizeof akan kembali 0. Ada beberapa jawaban skor tinggi dari pengguna reputasi tinggi yang mengatakan bahwa dengan standar tidak ada tipe atau variabel dapat memiliki sizeof 0. Dan saya setuju 100% dengan itu.

Namun ada jawaban baru ini yang menyajikan solusi ini:

struct ZeroMemory {
    int *a[0];
};

Saya baru saja akan memilih dan mengomentarinya, tetapi waktu yang dihabiskan di sini mengajari saya untuk memeriksa bahkan hal-hal yang saya yakin 100%. Jadi ... yang mengejutkan saya gcc dan clang menunjukkan hasil yang sama: sizeof(ZeroMemory) == 0. Lebih dari itu, ukuran dari suatu variabel adalah 0:

ZeroMemory z{};
static_assert(sizeof(z) == 0); // Awkward...

Whaaaat ...?

Tautan Godbolt

Bagaimana ini mungkin?


75
2017-11-17 14:14


asal


Jawaban:


Sebelum C distandardisasi, banyak kompiler tidak akan kesulitan menangani jenis ukuran-nol selama kode tidak pernah mencoba mengurangi satu penunjuk ke tipe nol dari yang lain. Jenis seperti itu berguna, dan mendukungnya lebih mudah dan lebih murah daripada melarangnya. Penyusun lain memutuskan untuk melarang jenis-jenis tersebut, bagaimanapun, dan beberapa kode pernyataan statis mungkin telah mengandalkan fakta bahwa mereka akan mengomel jika kode mencoba untuk membuat array berukuran nol. Para penulis Standar dihadapkan pada pilihan:

  1. Izinkan kompiler untuk diam-diam menerima deklarasi array berukuran nol, bahkan dalam kasus di mana tujuan deklarasi tersebut akan memicu kompilasi diagnostik dan abort, dan mengharuskan semua compiler menerima deklarasi semacam itu (meskipun tidak harus diam-diam) sebagai produksi nol benda berukuran.

  2. Izinkan kompiler untuk diam-diam menerima deklarasi array berukuran nol, bahkan dalam kasus di mana tujuan deklarasi tersebut akan memicu kompilasi diagnostik dan abort, dan memungkinkan compiler menghadapi hal tersebut deklarasi baik untuk membatalkan kompilasi atau melanjutkannya di waktu luang mereka.

  3. Perlu bahwa implementasi mengeluarkan diagnostik jika kode menyatakan a array berukuran nol, tetapi kemudian memungkinkan implementasi untuk membatalkan kompilasi atau melanjutkannya (dengan semantik apa pun yang mereka mau) di waktu luang mereka.

Penulis Standar memilih untuk # 3. Akibatnya, deklarasi array berukuran nol dianggap oleh "ekstensi" Standar, meskipun konstruksi seperti itu secara luas didukung sebelum Standar melarang mereka.

Standar C ++ memungkinkan untuk keberadaan objek kosong, tetapi dalam upaya untuk memungkinkan alamat objek kosong untuk digunakan sebagai token yang mengamanatkan bahwa mereka memiliki ukuran minimum 1. Untuk objek yang tidak memiliki anggota untuk memiliki ukuran 0 dengan demikian akan melanggar Standar. Jika sebuah objek berisi anggota berukuran nol, bagaimanapun, C ++ Standard tidak membebankan persyaratan tentang bagaimana itu diproses di luar fakta bahwa program yang mengandung deklarasi tersebut harus memicu diagnostik. Karena sebagian besar kode yang menggunakan deklarasi tersebut mengharapkan objek yang dihasilkan memiliki ukuran nol, perilaku yang paling berguna untuk compiler yang menerima kode tersebut adalah memperlakukannya seperti itu.


49
2017-11-17 18:18



Seperti yang ditunjukkan oleh Jarod42ukuran nol array tidak standar C ++, tetapi ekstensi GCC dan Clang.

Menambah -pedantic menghasilkan peringatan ini:

5 : <source>:5:12: warning: zero size arrays are an extension [-Wzero-length-array]
    int *a[0];
           ^

Saya selalu lupa itu std=c++XX (dari pada std=gnu++XX) tidak menonaktifkan semua ekstensi.

Ini masih belum menjelaskan sizeof tingkah laku. Tapi setidaknya kita tahu itu bukan standar ...


39
2017-11-17 14:19



Dalam C ++, array berukuran nol adalah ilegal.

ISO / IEC 14882: 2003 8.3.4 / 1:

[..] Jika ekspresi konstan (5.19) hadir, itu akan menjadi ekspresi konstan integral dan nilainya harus lebih besar dari nol. Ekspresi konstan menentukan batas (jumlah elemen dalam) array. Jika nilai dari ekspresi konstan adalah N, Array memiliki N elemen bernomor 0 untuk N-1, dan jenis pengidentifikasi D aku s "turunan-deklarator-tipe-daftar susunan dari N T ”. [..]

g ++ membutuhkan -pedantic bendera untuk memberi peringatan pada larik berukuran nol.


17
2017-11-17 14:28



Zero length array adalah ekstensi oleh GCC dan Clang. Menerapkan sizeof ke array tanpa panjang mengevaluasi ke nol.

Kelas C ++ (kosong) tidak dapat memiliki ukuran 0, tetapi perhatikan bahwa kelas ZeroMemory tidak kosong. Ini memiliki anggota bernama dengan ukuran 0 dan menerapkan sizeof akan mengembalikan nol.


4
2017-11-17 16:16