Pertanyaan Bagaimana cara menginisialisasi semua anggota array ke nilai yang sama?


Saya memiliki array besar dalam C (bukan C ++ jika itu membuat perbedaan). Saya ingin menginisialisasi semua anggota ke nilai yang sama. Saya berani bersumpah saya pernah tahu cara sederhana untuk melakukan ini. Saya bisa menggunakan memset() dalam kasus saya, tetapi tidak ada cara untuk melakukan ini yang dibangun tepat ke sintaks C?


789
2017-10-14 13:13


asal


Jawaban:


Kecuali nilai itu adalah 0 (dalam hal ini Anda dapat menghilangkan beberapa bagian dari penginisialisasi dan elemen terkait akan diinisialisasi ke 0), tidak ada cara mudah.

Jangan mengabaikan solusi yang jelas, meskipun:

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };

Elemen dengan nilai yang hilang akan diinisialisasi ke 0:

int myArray[10] = { 1, 2 }; // initialize to 1,2,0,0,0...

Jadi ini akan menginisialisasi semua elemen ke 0:

int myArray[10] = { 0 }; // all elements 0

Dalam C ++, daftar inisialisasi kosong juga akan menginisialisasi setiap elemen ke 0. Ini adalah tidak diizinkan dengan C:

int myArray[10] = {}; // all elements 0 in C++

Ingat bahwa objek dengan durasi penyimpanan statis akan diinisialisasi ke 0 jika tidak penginisialisasi ditentukan:

static int myArray[10]; // all elements 0

Dan itu "0" tidak selalu berarti "semua-bit-nol", jadi menggunakan di atas adalah lebih baik dan lebih portabel daripada memset (). (Nilai titik mengambang akan menjadi diinisialisasi ke +0, pointer ke nilai nol, dll.)


1028
2017-10-14 13:17



Jika compiler Anda adalah GCC, Anda dapat menggunakan sintaks berikut:

int array[1024] = {[0 ... 1023] = 5};

Lihat deskripsi terperinci: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


348
2017-10-16 07:38



Untuk menginisialisasi array besar secara statis dengan nilai yang sama, tanpa beberapa salin-tempel, Anda dapat menggunakan makro:

#define VAL_1X     42
#define VAL_2X     VAL_1X,  VAL_1X
#define VAL_4X     VAL_2X,  VAL_2X
#define VAL_8X     VAL_4X,  VAL_4X
#define VAL_16X    VAL_8X,  VAL_8X
#define VAL_32X    VAL_16X, VAL_16X
#define VAL_64X    VAL_32X, VAL_32X

int myArray[53] = { VAL_32X, VAL_16X, VAL_4X, VAL_1X };

Jika Anda perlu mengubah nilainya, Anda harus melakukan penggantian hanya di satu tempat.

Edit: kemungkinan ekstensi yang bermanfaat

(courtesy of Jonathan Leffler)

Anda dapat dengan mudah menyamaratakan ini dengan:

#define VAL_1(X) X
#define VAL_2(X) VAL_1(X), VAL_1(X)
/* etc. */

Varian dapat dibuat menggunakan:

#define STRUCTVAL_1(...) { __VA_ARGS__ }
#define STRUCTVAL_2(...) STRUCTVAL_1(__VA_ARGS__), STRUCTVAL_1(__VA_ARGS__)
/*etc */ 

yang berfungsi dengan struktur atau susunan majemuk.

#define STRUCTVAL_48(...) STRUCTVAL_32(__VA_ARGS__), STRUCTVAL_16(__VA_ARGS__)

struct Pair { char key[16]; char val[32]; };
struct Pair p_data[] = { STRUCTVAL_48("Key", "Value") };
int a_data[][4] = { STRUCTVAL_48(12, 19, 23, 37) };

nama makro bisa dinegosiasikan.


161
2017-10-14 10:27



Jika Anda ingin memastikan bahwa setiap anggota array secara eksplisit diinisialisasi, hilangkan saja dimensi dari deklarasi:

int myArray[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Compiler akan menyimpulkan dimensi dari daftar penginisialisasi. Sayangnya, untuk array multidimensi hanya dimensi terluar dapat dihilangkan:

int myPoints[][3] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

oke, tapi

int myPoints[][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };

tidak.


59
2017-10-14 18:30



Saya melihat beberapa kode yang menggunakan sintaks ini:

char* array[] = 
{
    [0] = "Hello",
    [1] = "World"
};   

Di mana itu menjadi sangat berguna adalah jika Anda membuat sebuah array yang menggunakan enums sebagai indeks:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

#define _ITEM(x) [x] = #x

char* array[] = 
{
    _ITEM(ERR_OK),
    _ITEM(ERR_FAIL),
    _ITEM(ERR_MEMORY)
};   

Hal ini menjaga semuanya teratur, bahkan jika Anda menulis beberapa nilai enum-out yang rusak.

Lebih lanjut tentang teknik ini dapat ditemukan sini dan sini.


45
2018-03-21 21:02



int i;
for (i = 0; i < ARRAY_SIZE; ++i)
{
  myArray[i] = VALUE;
}

Saya pikir ini lebih baik daripada

int myArray[10] = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5...

memetikan ukuran dari perubahan array.


22
2017-10-14 13:34



Anda dapat melakukan seluruh hal penginisialisasi statis seperti yang dijelaskan di atas, tetapi ini bisa menjadi sampah nyata ketika ukuran array Anda berubah (ketika array Anda embiggens, jika Anda tidak menambahkan initializers tambahan yang tepat Anda mendapatkan sampah).

memset memberi Anda hit runtime untuk melakukan pekerjaan, tetapi tidak ada ukuran kode yang berhasil dilakukan kebal terhadap perubahan ukuran larik. Saya akan menggunakan solusi ini di hampir semua kasus ketika array lebih besar dari, katakanlah, beberapa lusin elemen.

Jika itu benar-benar penting bahwa array itu statis dinyatakan, saya akan menulis sebuah program untuk menulis program untuk saya dan menjadikannya bagian dari proses membangun.


11
2017-10-14 13:29



Inilah cara lain:

static void
unhandled_interrupt(struct trap_frame *frame, int irq, void *arg)
{
    //this code intentionally left blank
}

static struct irqtbl_s vector_tbl[XCHAL_NUM_INTERRUPTS] = {
    [0 ... XCHAL_NUM_INTERRUPTS-1] {unhandled_interrupt, NULL},
};

Lihat:

C-Extensions

Inits yang ditunjuk

Kemudian ajukan pertanyaan: Kapan seseorang dapat menggunakan ekstensi C?

Contoh kode di atas adalah dalam sistem tertanam dan tidak akan pernah melihat cahaya dari kompiler lain.


8
2017-10-14 22:12



Untuk menginisialisasi tipe data 'normal' (seperti int array), Anda dapat menggunakan notasi braket, tetapi akan nol nilai setelah yang terakhir jika masih ada ruang dalam array:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};

5
2017-10-14 13:17