Hanya ingin tahu, apa yang sebenarnya terjadi jika saya mendefinisikan array nol-panjang int array[0];
dalam kode? GCC tidak mengeluh sama sekali.
Program Sampel
#include <stdio.h>
int main() {
int arr[0];
return 0;
}
Klarifikasi
Saya benar-benar mencoba mencari tahu apakah array panjang nol diinisialisasi dengan cara ini, bukannya diarahkan seperti panjang variabel dalam komentar Darhazer, dioptimalkan atau tidak.
Ini karena saya harus merilis beberapa kode keluar ke alam, jadi saya mencoba mencari tahu apakah saya harus menangani kasus-kasus di mana SIZE
didefinisikan sebagai 0
, yang terjadi dalam beberapa kode dengan yang didefinisikan secara statisint array[SIZE];
Saya sebenarnya terkejut bahwa GCC tidak mengeluh, yang menyebabkan pertanyaan saya. Dari jawaban yang saya terima, saya percaya kurangnya peringatan sebagian besar karena mendukung kode lama yang belum diperbarui dengan sintaks [] baru.
Karena saya terutama bertanya-tanya tentang kesalahan, saya menandai jawaban Lundin sebagai benar (Nawaz pertama, tetapi tidak lengkap) - yang lain menunjukkan penggunaannya yang sebenarnya untuk struktur berlapis ekor, sementara yang relevan, bukan t persis apa yang saya cari.
[]
Python atau bahkan""
dalam C? Terkadang, Anda memiliki fungsi atau makro yang membutuhkan array, tetapi Anda tidak memiliki data untuk dimasukkan ke dalamnya.Jawaban:
Array tidak boleh memiliki ukuran nol.
ISO 9899: 2011 6.7.6.2:
Teks di atas benar untuk array biasa (paragraf 1). Untuk VLA (array panjang variabel), perilaku tidak terdefinisi jika nilai ekspresi kurang dari atau sama dengan nol (paragraf 5). Ini adalah teks normatif dalam standar C. Kompiler tidak diizinkan untuk mengimplementasikannya secara berbeda.
gcc -std=c99 -pedantic
memberikan peringatan untuk kasus non-VLA.sumber
#error
arahan.#error
arahan preprosesor.Sesuai standar, itu tidak diperbolehkan.
Namun sudah menjadi praktik saat ini dalam kompiler C untuk memperlakukan deklarasi tersebut sebagai deklarasi anggota array fleksibel ( FAM ) :
Sintaks standar FAM adalah:
Idenya adalah Anda akan mengalokasikannya demikian:
Anda mungkin juga menggunakannya secara statis (ekstensi gcc):
Ini juga dikenal sebagai struktur berlapis-empuk (istilah ini ada sebelum penerbitan Standar C99) atau struct hack (terima kasih kepada Joe Wreschnig karena menunjukkannya).
Namun sintaks ini distandarisasi (dan efeknya dijamin) hanya belakangan ini di C99. Sebelum ukuran konstan diperlukan.
1
adalah cara portabel untuk pergi, meskipun agak aneh.0
lebih baik dalam menunjukkan niat, tetapi tidak sah sejauh Standar terkait dan didukung sebagai perpanjangan oleh beberapa penyusun (termasuk gcc).Praktik padding tail, bagaimanapun, bergantung pada kenyataan bahwa penyimpanan tersedia (hati-hati
malloc
) sehingga tidak cocok untuk menumpuk penggunaan secara umum.sumber
int content[];
di sini sejauh yang saya mengerti. Karena saya tidak terlalu paham tentang persyaratan C dari seni ... bisakah Anda mengkonfirmasi apakah alasan saya tampaknya benar?foo[x]
kefoo[0]
setiap kalifoo
array elemen tunggal.Dalam Standar C dan C ++, array ukuran-nol tidak diperbolehkan ..
Jika Anda menggunakan GCC, kompilasi dengan
-pedantic
opsi. Ini akan memberi peringatan , mengatakan:Dalam kasus C ++, ia memberikan peringatan serupa.
sumber
error C2466: cannot allocate an array of constant size 0
[BCC32 Error] test.c(3): E2021 Array must have at least one element
-pedantic -Werror
, Anda juga bisa melakukannya-pedantic-errors
std::array
. (Selain: Saya ingat tetapi tidak dapat menemukan sumber yang dipertimbangkan dan secara eksplisit ditolak VLA dari berada di C ++.)Benar-benar ilegal, dan selalu demikian, tetapi banyak penyusun mengabaikan sinyal kesalahan. Saya tidak yakin mengapa Anda ingin melakukan ini. Satu penggunaan yang saya tahu adalah untuk memicu kesalahan waktu kompilasi dari boolean:
Jika
condition
salah, maka saya mendapatkan kesalahan waktu kompilasi. Karena kompiler mengizinkan ini, saya menggunakan:Ini memberikan ukuran 1 atau -1, dan saya tidak pernah menemukan kompiler yang akan menerima ukuran -1.
sumber
STATIC_ASSERT
menggunakannya.#if condition \n #error whatever \n #endif
Saya akan menambahkan bahwa ada seluruh halaman dokumentasi online gcc pada argumen ini.
Beberapa kutipan:
dan
jadi kamu bisa
dan booming :-)
sumber
int a[0]
, makaa[0] = 1
a[1] = 2
??a[100000] = 5
tetapi jika Anda beruntung Anda hanya akan crash aplikasi Anda, jika Anda beruntung: -)Penggunaan lain dari array panjang-nol adalah untuk membuat objek panjang variabel (pra-C99). Zero-panjang array yang berbeda dari array yang fleksibel yang memiliki [] tanpa 0.
Dikutip dari gcc doc :
Contoh dunia nyata adalah array panjang nol
struct kdbus_item
di kdbus.h (modul kernel Linux).sumber
void*
tujuan aritmatika (sehingga menambah atau mengurangi pointer ke benda berukuran nol akan dilarang). Sementara Fleksibel Anggota Array sebagian besar lebih baik daripada array berukuran nol, mereka juga dapat bertindak sebagai semacam "persatuan" untuk alias hal-hal tanpa menambahkan tingkat tambahan "sindiran" tipuan untuk apa yang mengikuti (misalnya diberikanstruct foo {unsigned char as_bytes[0]; int x,y; float z;}
seseorang dapat mengakses anggotax
..z
...myStruct.asFoo.x
, dll. Lebih lanjut, IIRC, C squawks pada setiap upaya untuk memasukkan anggota array yang fleksibel dalam sebuah struct, sehingga membuatnya tidak mungkin memiliki struktur yang mencakup beberapa anggota array fleksibel lainnya dengan panjang yang diketahui. kandungan.sizeof x->contents
merupakan kesalahan dalam ISO C sebagai lawan mengembalikan 0 dalam gcc. Array berukuran nol yang bukan anggota struct memperkenalkan banyak masalah lain.struct {int n; THING dat[];}
dan dapat bekerja dengan hal-hal durasi statis atau otomatis.Deklarasi array ukuran-nol dalam struct akan berguna jika diizinkan, dan jika semantiknya sedemikian sehingga (1) mereka akan memaksa penyelarasan tetapi jika tidak mengalokasikan ruang apa pun, dan (2) mengindeks array akan dianggap perilaku yang didefinisikan dalam kasus di mana pointer yang dihasilkan akan berada dalam blok memori yang sama dengan struct. Perilaku seperti itu tidak pernah diizinkan oleh standar C apa pun, tetapi beberapa kompiler lama mengizinkannya sebelum menjadi standar bagi kompiler untuk memungkinkan deklarasi array tidak lengkap dengan kurung kosong.
Struct hack, seperti yang biasa diimplementasikan menggunakan array ukuran 1, adalah cerdik dan saya tidak berpikir ada persyaratan yang kompiler menahan diri dari melanggar itu. Sebagai contoh, saya akan berharap bahwa jika seorang kompiler melihat
int a[1]
, itu akan menjadi haknya untuk menganggapnyaa[i]
sebagaia[0]
. Jika seseorang mencoba mengatasi masalah penyelarasan struct hack melalui sesuatu sepertikompiler mungkin menjadi pintar dan menganggap ukuran array benar-benar empat:
Optimalisasi semacam itu mungkin masuk akal, terutama jika
myStruct->data
dapat dimuat ke dalam register dalam operasi yang sama denganmyStruct->size
. Saya tidak tahu apa-apa dalam standar yang akan melarang optimasi seperti itu, meskipun tentu saja itu akan merusak kode apa pun yang mungkin berharap untuk mengakses barang-barang di luar elemen keempat.sumber