Kesalahan kompilasi C: "Objek berukuran variabel mungkin tidak diinisialisasi"

97

Mengapa saya menerima pesan kesalahan "Objek berukuran variabel mungkin tidak dimulai" dengan kode berikut?

int boardAux[length][length] = {{0}};
Halo Dunia
sumber
Seperti yang ditunjukkan dalam jawaban yang sangat bagus oleh David Rodriguez: jika panjang adalah variabel, Anda perlu memset, tetapi jika panjang adalah konstanta waktu kompilasi, maka pernyataan dikompilasi dengan baik.
Casey
ffwd hingga 2020 -enum {length = 0xF } ; int boardAux[length][length] = {0};
Chef Gladiator

Jawaban:

121

Saya berasumsi bahwa Anda menggunakan kompiler C99 (dengan dukungan untuk array berukuran dinamis). Masalah dalam kode Anda adalah bahwa pada saat kompiler melihat deklarasi variabel Anda, ia tidak dapat mengetahui berapa banyak elemen yang ada dalam array (saya juga mengasumsikan di sini, dari kesalahan kompiler yang lengthbukan konstanta waktu kompilasi).

Anda harus menginisialisasi array itu secara manual:

int boardAux[length][length];
memset( boardAux, 0, length*length*sizeof(int) );
David Rodríguez - dribeas
sumber
Saya dapat menggunakan malloc untuk tujuan ini juga, bagaimana dengan pertanyaan kedua, saya menulisnya setelah balasan Pavel
helloWorld
@ HelloWorld: Dengan tumpukan array yang dialokasikan, printf( "%d", boardAux[1][2] )kompilasi dengan baik. Kompilator mengetahui ukurannya dan mengetahui di posisi apa elemen (1,2) dalam memori itu. Jika Anda menggunakan alokasi dinamis, lariknya uni-dimensional dan Anda harus menghitung sendiri:printf("%d", boardAux[ 1*length + 2 ])
David Rodríguez - dribeas
@AndreyT: Terima kasih telah menunjukkan kesalahan saat memsetmenelepon. Saya baru saja memperbaikinya.
David Rodríguez - dribeas
Mengapa saya mendapatkan kesalahan ini pada compiler C99 ketika saya menyetel lengthmenjadi static? Di C ++ 14 ini berfungsi dengan baik.
Muhamed Cicak
25

Anda menerima kesalahan ini karena dalam bahasa C Anda tidak diperbolehkan menggunakan penginisialisasi dengan array panjang variabel. Pesan kesalahan yang Anda dapatkan pada dasarnya mengatakan itu semua.

6.7.8 Inisialisasi

...

3 Jenis entitas yang akan diinisialisasi adalah larik dengan ukuran tidak diketahui atau tipe objek yang bukan jenis larik dengan panjang variabel.

Semut
sumber
di mana Anda menemukan ini, dapatkah Anda memberi saya tautan?
helloWorld
1
@ HelloWorld: Ini dari standar bahasa (C99). Anda bisa mendapatkan "bekerja" copy dengan TC3 update disini open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
ANT
5
Ada subjek yang sebagian akan selalu tidak mempercayai Anda jika Anda hanya memberikan penjelasan informal. Larik panjang variabel adalah salah satu topik ini. 1 untuk mengutip standar.
Pascal Cuoq
15

Ini memberikan kesalahan:

int len;
scanf("%d",&len);
char str[len]="";

Ini juga memberikan kesalahan:

int len=5;
char str[len]="";

Tapi ini berfungsi dengan baik:

int len=5;
char str[len]; //so the problem lies with assignment not declaration

Anda perlu memberi nilai dengan cara berikut:

str[0]='a';
str[1]='b'; //like that; and not like str="ab";
Amitesh Ranjan
sumber
2

Setelah mendeklarasikan array

int boardAux[length][length];

cara termudah untuk menetapkan nilai awal sebagai nol adalah menggunakan for loop, meskipun mungkin agak panjang

int i, j;
for (i = 0; i<length; i++)
{
    for (j = 0; j<length; j++)
        boardAux[i][j] = 0;
}
Krishna Shrestha
sumber
2
memsetlebih sederhana dan lebih cepat.
Cacahuete Frito
1

Pertanyaannya sudah dijawab tetapi saya ingin menunjukkan solusi lain yang cepat dan berfungsi jika panjang tidak dimaksudkan untuk diubah pada saat run-time. Gunakan makro #define before main () untuk menentukan panjang dan di main () inisialisasi Anda akan bekerja:

#define length 10

int main()
{
    int boardAux[length][length] = {{0}};
}

Makro dijalankan sebelum kompilasi aktual dan panjangnya akan menjadi konstanta waktu kompilasi (seperti yang dirujuk oleh David Rodríguez dalam jawabannya). Ini sebenarnya akan menggantikan panjang dengan 10 sebelum kompilasi.

Sergey
sumber
0

Cukup nyatakan panjang sebagai kontra, jika tidak maka Anda harus mengalokasikan memori secara dinamis

Azizou
sumber
2
Saya pikir Anda perlu mencari apa arti const!
Holger
@Holger: Apakah Anda yakin? Jika variabel yang menahan panjang (bukan array itu sendiri, tetapi panjang array) adalah konstanta, maka compiler mengetahui panjang yang akan digunakan untuk menginisialisasi array. Misalnya, "int length = 5; int array [length];" memberikan kesalahan tetapi " const int length = 5; int array [length];" mengkompilasi dengan baik.
Casey
0
int size=5;
int ar[size ]={O};

/* This  operation gives an error -  
variable sized array may not be 
initialised.  Then just try this. 
*/
int size=5,i;
int ar[size];
for(i=0;i<size;i++)
{
    ar[i]=0;
}
Codetheft
sumber
1
Selamat datang di Stack Overflow! Silakan baca panduan tentang cara menulis jawaban yang baik: stackoverflow.com/help/how-to-answer Jawaban Anda saat ini tampaknya tidak jelas dan tidak memiliki penjelasan apa pun
gybandi
-5

Untuk C ++ deklarasi dan inisialisasi terpisah seperti ini ..

int a[n][m] ;
a[n][m]= {0};
Munawir
sumber
1
Bukan pertanyaan C ++
Cacahuete Frito
Di atas hanya menginisialisasi A [n] [m], bukan seluruh larik. int a [n] [m]; memset (a, 0, (n m sizeof (int)); // hapus mem of array Kebanyakan kompiler mengizinkan ini: int a [n] [m] = {0}; // inisialisasi semua anggota ke 0
Chris Reid
-9

Kamu tidak dapat melakukannya. Kompiler C tidak dapat melakukan hal yang rumit pada stack.

Anda harus menggunakan heap dan alokasi dinamis.

Apa yang benar-benar perlu Anda lakukan:

  • menghitung ukuran (n m sizeof (elemen)) dari memori yang Anda butuhkan
  • panggil malloc (size) untuk mengalokasikan memori
  • buat pengakses: int * access (ptr, x, y, rowSize) {return ptr + y * rowSize + x; }

Gunakan * akses (boardAux, x, y, size) = 42 untuk berinteraksi dengan matriks.

Pavel Radzivilovsky
sumber
satu pertanyaan lagi, mengapa saya menerima kesalahan penggunaan array yang tidak valid dengan batas yang tidak ditentukan? printf ("% d", papan [i] [j]);
helloWorld
10
-1 C99 memungkinkan alokasi dinamis dalam tumpukan sebagai kode pengguna (tidak termasuk inisialisasi). Tidak perlu melakukan alokasi dinamis.
David Rodríguez - dribeas
@ HelloWorld karena dimensi array harus diketahui.
Pavel Radzivilovsky