Bagaimana cara menginisialisasi semua anggota array dengan nilai yang sama?

968

Saya memiliki array besar di C (bukan C ++ jika itu membuat perbedaan). Saya ingin menginisialisasi semua anggota dengan nilai yang sama.

Aku bersumpah aku pernah tahu cara sederhana untuk melakukan ini. Saya dapat menggunakan memset()dalam kasus saya, tetapi tidak adakah cara untuk melakukan ini yang dibangun langsung ke dalam sintaks C?

Mat
sumber
16
Sejauh ini tidak ada jawaban yang menyebutkan notasi initializer yang ditunjuk yang layak dengan C99 dan di atasnya. Misalnya: enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };dan struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };. Jika Anda menghapus elipsis , fragmen-fragmen itu mengkompilasi di bawah C99 atau C11.
Jonathan Leffler
Sebenarnya jawaban abelenky menggunakan inisialisasi yang ditunjuk, tetapi tidak sepenuhnya membentuk kode inisialisasi
Rob11311
memset () dapat membantu, tetapi tergantung dari nilainya.
Nick
2
memset()diskusi spesifik: stackoverflow.com/questions/7202411/... Saya pikir ini hanya berfungsi untuk 0.
Ciro Santilli 郝海东 冠状 病 六四 事件 事件

Jawaban:

1239

Kecuali jika nilainya 0 (dalam hal ini Anda dapat menghilangkan beberapa bagian dari penginisialisasi dan elemen yang sesuai akan diinisialisasi ke 0), tidak ada cara mudah.

Namun, jangan mengabaikan solusi yang jelas:

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

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

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

Ingatlah bahwa objek dengan durasi penyimpanan statis akan diinisialisasi ke 0 jika tidak ada initializer yang ditentukan:

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

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

aib
sumber
27
Membaca standar C ++, Anda juga dapat melakukan array int [10] = {}; ke nol inisialisasi. Saya tidak memiliki standar C untuk memeriksa apakah ini valid juga.
workmad3
54
Melihat bagian 6.7.8 Inisialisasi standar C99, tampaknya daftar penginisialisasi kosong tidak diizinkan.
Jonathan Leffler
7
C99 memiliki banyak fitur bagus untuk inisialisasi struktur dan array; satu fitur yang tidak dimilikinya (tetapi Fortran IV, 1966, miliki) adalah cara untuk mengulang penginisialisasi tertentu untuk sebuah array.
Jonathan Leffler
8
@CetinSert: Apa maksud Anda ini tidak berhasil? Itu tepat seperti yang seharusnya dilakukan oleh jawaban ini. Itu tidak melakukan apa yang dikatakan komentar dalam kode Anda, tetapi komentar itu salah.
Benjamin Lindley
9
@CetinSert: Anda satu-satunya yang mengklaim, dalam komentar itu, bahwa semua elemen akan disetel ke -1. Jawaban ini mengklaim, dengan benar, bahwa semua elemen yang tidak ditentukan diatur ke nol. Hasil kode Anda sesuai dengan klaim ini.
Benjamin Lindley
394

Jika kompiler 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

qrdl
sumber
12
Dan sintaksis itu menyebabkan peningkatan besar dalam ukuran file biner yang dikompilasi. Untuk N = 65536 (bukan 1024), biner saya melonjak dari ukuran 15 KB menjadi 270 KB !!
Cetin Sert
50
@CetinSert Compiler harus menambahkan 65536 ints ke dalam data statis, yaitu 256 K - persis peningkatan ukuran yang Anda amati.
qrdl
15
@CetinSert Kenapa saya harus? Ini adalah perilaku kompiler standar, tidak spesifik untuk inisialisasi yang ditunjuk. Jika Anda menginisialisasi 65536 ints secara statis , seperti int foo1 = 1, foo2 = 1, ..., foo65536 =1;Anda akan mendapatkan peningkatan ukuran yang sama.
qrdl
27
lebih baik lagi: "int array [] = {[0 ... 1023] = 5}", ukuran array akan secara otomatis diatur ke 1024, lebih mudah dan lebih aman untuk dimodifikasi.
Francois
4
@ Francois atau untuk array 2d bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}, meskipun saya tidak yakin itu lebih mudah dibaca daripada bentuk lengkap.
g33kz0r
178

Untuk menginisialisasi array besar secara statis dengan nilai yang sama, tanpa beberapa copy-paste, 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 berguna

(milik Jonathan Leffler )

Anda dapat dengan mudah menggeneralisasi 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 bekerja 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.

mouviciel
sumber
12
Saya hanya akan mempertimbangkan ini dalam kasus-kasus ekstrem, pasti memset adalah cara yang lebih elegan untuk mengekspresikannya.
u0b34a0f6ae
47
Jika data harus dapat di-ROM, memset tidak dapat digunakan.
Kontrak Prof. Falken dilanggar pada
9
Preprocessor sebenarnya akan menghasilkan kode dari #defines. Dengan dimensi array yang lebih besar ukuran yang dapat dieksekusi akan tumbuh. Tapi pasti + untuk idenya;)
Leonid
7
@Alcott, pada komputer lama dan masih pada banyak sistem yang disematkan, kode ini akhirnya ditempatkan di EPROM atau ROM . ROM-mampu juga berarti, dalam sistem tertanam, "kode dimasukkan ke dalam flash", karena memiliki implikasi yang sama, yaitu bahwa memori tidak dapat ditulis runtime. Yaitu memset atau instruksi lain untuk memperbarui atau mengubah memori tidak dapat digunakan. Konstanta, bagaimanapun, dapat diekspresikan dan dipasang atau di-ROM sebelum program dimulai.
Kontrak Prof. Falken dilanggar
4
@ u0b34a0f6ae: Perlu diingat bahwa Anda dapat menggunakan metode ini juga jika VAL_1Xbukan bilangan bulat tunggal tetapi daftar. Seperti negara yang Dapat Diakses, ini juga merupakan cara untuk menggunakan sistem embedded di mana Anda ingin mendefinisikan nilai init dari EEPROM atau memori Flash. Dalam kedua kasus, Anda tidak dapat menggunakan memset().
Martin Scharrer
63

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

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

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

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

tidak apa-apa, tapi

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

tidak.

Frank Szczerba
sumber
Apakah ini benar ? int myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Praveen Gowda IV
10
Tidak. Anda menghilangkan dimensi paling dalam, yang tidak diizinkan. Ini akan memberikan kesalahan kompiler.
Frank Szczerba
4
Inisialisasi dan inferensi panjang diperkenalkan pada C99.
Palec
3
@Palec: Tidak - inferensi panjang telah ada di C sejak zaman pra-standar C (sejak K&R Edisi Pertama diterbitkan, dan mungkin beberapa saat sebelumnya). Inisialisasi yang ditunjuk baru di C99, tetapi ini tidak menggunakan inisialisasi yang ditunjuk.
Jonathan Leffler
53

Saya melihat beberapa kode yang menggunakan sintaks ini:

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

Di mana itu menjadi sangat berguna adalah jika Anda membuat array yang menggunakan enum 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)
};   

Ini menjaga segala sesuatunya tetap teratur, bahkan jika Anda menulis beberapa nilai enum di luar urutan.

Lebih lanjut tentang teknik ini dapat ditemukan di sini dan di sini .

kasar
sumber
8
Ini adalah sintaks initializer C99, yang sudah dicakup oleh beberapa jawaban lain. Anda dapat dengan bermanfaat membuat deklarasi menjadi char const *array[] = { ... };atau bahkan char const * const array[] = { ... };, bukan?
Jonathan Leffler
22
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 perubahan array.

Tarski
sumber
12
Sebagai catatan, itu pada dasarnya hanya versi yang lebih lambat dan lebih verbal darimemset(myArray, VALUE, ARRAY_SIZE);
Benson
18
Bagaimana Anda menggunakan memset untuk menginisialisasi array int ke beberapa nilai yang lebih besar dari 255? memset hanya berfungsi jika array berukuran byte.
Matt
21
@Benson: Anda tidak dapat mengganti kode di atas dengan memset pada platform di mana sizeof (int)> sizeof (char). Cobalah.
ChrisWue
13

Anda dapat melakukan hal inisialisasi statis keseluruhan seperti yang dijelaskan di atas, tetapi ini bisa sangat menyebalkan ketika ukuran array Anda berubah (ketika array Anda embiggens, jika Anda tidak menambahkan inisialisasi tambahan yang sesuai Anda mendapatkan sampah).

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

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

alas tiang
sumber
Bisakah Anda menambahkan beberapa contoh tentang penggunaan memsetuntuk menginisialisasi array?
Sopalajo de Arrierez
8

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

humble_guru
sumber
6

Untuk menginisialisasi tipe data 'normal' (seperti array int), 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};
warren
sumber
5

Jika array kebetulan adalah int atau apa pun dengan ukuran int atau ukuran pola mem Anda cocok dengan waktu yang tepat menjadi int (yaitu semua nol atau 0xA5A5A5A5), cara terbaik adalah menggunakan memset () .

Kalau tidak panggil memcpy () dalam satu lingkaran untuk memindahkan indeks.

ddimitrov
sumber
5

Jawaban yang sedikit tidak jelas; tulis pernyataannya

array = initial_value

dalam bahasa yang mampu menggunakan array favorit Anda (milik saya adalah Fortran, tetapi ada banyak lainnya), dan menautkannya ke kode C Anda. Anda mungkin ingin membungkusnya menjadi fungsi eksternal.

Tanda Kinerja Tinggi
sumber
4

Ada cara cepat untuk menginisialisasi array jenis apa pun dengan nilai yang diberikan. Ini bekerja sangat baik dengan array yang besar. Algoritma adalah sebagai berikut:

  • inisialisasi elemen pertama array (cara biasa)
  • salin bagian yang telah ditetapkan menjadi bagian yang belum diatur, menggandakan ukuran setiap operasi salin berikutnya

Untuk 1 000 000elemen intarray, ini 4 kali lebih cepat dari inisialisasi loop biasa (i5, 2 core, 2.3 GHz, memori 4GiB, 64 bit):

loop runtime 0.004248 [seconds]

memfill() runtime 0.001085 [seconds]


#include <stdio.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 1000000

void memfill(void *dest, size_t destsize, size_t elemsize) {
   char   *nextdest = (char *) dest + elemsize;
   size_t movesize, donesize = elemsize;

   destsize -= elemsize;
   while (destsize) {
      movesize = (donesize < destsize) ? donesize : destsize;
      memcpy(nextdest, dest, movesize);
      nextdest += movesize; destsize -= movesize; donesize += movesize;
   }
}    
int main() {
    clock_t timeStart;
    double  runTime;
    int     i, a[ARR_SIZE];

    timeStart = clock();
    for (i = 0; i < ARR_SIZE; i++)
        a[i] = 9;    
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("loop runtime %f [seconds]\n",runTime);

    timeStart = clock();
    a[0] = 10;
    memfill(a, sizeof(a), sizeof(a[0]));
    runTime = (double)(clock() - timeStart) / (double)CLOCKS_PER_SEC;
    printf("memfill() runtime %f [seconds]\n",runTime);
    return 0;
}
Maciej
sumber
2
Maaf, tapi ini tidak benar. Mungkin Anda lupa mengaktifkan optimisasi kompilasi selama pengujian (diuji dengan mode debug?). Jika saya menguji ini, loop hampir selalu 50% lebih cepat daripada memfill ('selalu' karena beberapa kegugupan beban pada mesin saya). Dan menggunakan memset (a, 0, sizeof (a)); bahkan dua kali lebih cepat dari loopfill.
RS1980
2
Seperti halnya kode tolok ukur apa pun, Anda harus sangat berhati-hati. Menambahkan loop untuk mengeksekusi kode timing 10 kali (dan menggandakan ukuran array menjadi 20M) menunjukkan - bagi saya, berjalan di MacBook Pro dengan macOS Sierra 10.12.3 dan menggunakan GCC 6.3.0 - yang pertama kali menggunakan loop membutuhkan sekitar 4600 μs, sedangkan memfill()kode membutuhkan sekitar 1200 μs. Namun, pada iterasi selanjutnya, loop membutuhkan sekitar 900-1000 μs sementara memfill()kode membutuhkan 1000-1300 μs. Iterasi pertama mungkin dipengaruhi oleh waktu untuk mengisi cache. Balikkan tes dan memfill()lambat pertama kali.
Jonathan Leffler
2

Tidak ada yang menyebutkan urutan indeks untuk mengakses elemen dari array yang diinisialisasi. Kode contoh saya akan memberikan contoh ilustrasi untuk itu.

#include <iostream>

void PrintArray(int a[3][3])
{
    std::cout << "a11 = " << a[0][0] << "\t\t" << "a12 = " << a[0][1] << "\t\t" << "a13 = " << a[0][2] << std::endl;
    std::cout << "a21 = " << a[1][0] << "\t\t" << "a22 = " << a[1][1] << "\t\t" << "a23 = " << a[1][2] << std::endl;
    std::cout << "a31 = " << a[2][0] << "\t\t" << "a32 = " << a[2][1] << "\t\t" << "a33 = " << a[2][2] << std::endl;
    std::cout << std::endl;
}

int wmain(int argc, wchar_t * argv[])
{
    int a1[3][3] =  {   11,     12,     13,     // The most
                        21,     22,     23,     // basic
                        31,     32,     33  };  // format.

    int a2[][3] =   {   11,     12,     13,     // The first (outer) dimension
                        21,     22,     23,     // may be omitted. The compiler
                        31,     32,     33  };  // will automatically deduce it.

    int a3[3][3] =  {   {11,    12,     13},    // The elements of each
                        {21,    22,     23},    // second (inner) dimension
                        {31,    32,     33} };  // can be grouped together.

    int a4[][3] =   {   {11,    12,     13},    // Again, the first dimension
                        {21,    22,     23},    // can be omitted when the 
                        {31,    32,     33} };  // inner elements are grouped.

    PrintArray(a1);
    PrintArray(a2);
    PrintArray(a3);
    PrintArray(a4);

    // This part shows in which order the elements are stored in the memory.
    int * b = (int *) a1;   // The output is the same for the all four arrays.
    for (int i=0; i<9; i++)
    {
        std::cout << b[i] << '\t';
    }

    return 0;
}

Outputnya adalah:

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

a11 = 11                a12 = 12                a13 = 13
a21 = 21                a22 = 22                a23 = 23
a31 = 31                a32 = 32                a33 = 33

11      12      13      21      22      23      31      32      33
hkBattousai
sumber
4
<iostream>tidak valid Ckarena std::cout,, std::cindll adalah bagian dari std::namespacedan Ctidak mendukung namespaces. Coba gunakan <stdio.h>untuk printf(...).
Francis Cugler
2

Memotong semua obrolan, jawaban singkatnya adalah jika Anda mengaktifkan optimisasi pada waktu kompilasi Anda tidak akan melakukan yang lebih baik dari ini:

int i,value=5,array[1000]; 
for(i=0;i<1000;i++) array[i]=value; 

Bonus tambahan: kode ini dapat dibaca :)

JWDN
sumber
7
Pertanyaan secara khusus meminta inisialisasi. Ini secara eksplisit bukan inisialisasi, tetapi tugas dilakukan setelah inisialisasi. Mungkin dilakukan segera, tetapi masih belum inisialisasi.
Andy
Sama sekali tidak membantu untuk tabel pencarian statis besar di dalam fungsi yang disebut berkali-kali.
Martin Bonner mendukung Monica
... jangan ingat tabel pencarian statis di dalam fungsi yang menjadi bagian dari pertanyaan awal - sederhananya Yang mengatakan, @Community mungkin berhasil.
JWDN
1
  1. Jika array Anda dinyatakan statis atau global, semua elemen dalam array sudah memiliki nilai default default 0.
  2. Beberapa kompiler menetapkan array sebagai default ke 0 dalam mode debug.
  3. Mudah untuk menetapkan default ke 0: int array [10] = {0};
  4. Namun, untuk nilai lain, Anda telah menggunakan memset () atau loop;

contoh: int array [10]; memset (array, -1, 10 * sizeof (int));

Hannah Zhang
sumber
0
#include<stdio.h>
int main(){
int i,a[50];
for (i=0;i<50;i++){
    a[i]=5;// set value 5 to all the array index
}
for (i=0;i<50;i++)
printf("%d\n",a[i]);
   return 0;
}

Ini akan memberikan o / p 5 5 5 5 5 5 ...... sampai ukuran seluruh array

Dadhich Sourav
sumber
0

Saya tahu pengguna Tarskimenjawab pertanyaan ini dengan cara yang sama, tetapi saya menambahkan beberapa detail lagi. Maafkan beberapa C saya karena saya agak berkarat karena saya lebih cenderung ingin menggunakan C ++, tapi begini saja.


Jika Anda mengetahui ukuran array sebelumnya ...

#include <stdio.h>

typedef const unsigned int cUINT;
typedef unsigned int UINT;

cUINT size = 10;
cUINT initVal = 5;

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal );
void printArray( UINT* myArray ); 

int main() {        
    UINT myArray[size]; 
    /* Not initialized during declaration but can be
    initialized using a function for the appropriate TYPE*/
    arrayInitializer( myArray, size, initVal );

    printArray( myArray );

    return 0;
}

void arrayInitializer( UINT* myArray, cUINT size, cUINT initVal ) {
    for ( UINT n = 0; n < size; n++ ) {
        myArray[n] = initVal;
    }
}

void printArray( UINT* myArray ) {
    printf( "myArray = { " );
    for ( UINT n = 0; n < size; n++ ) {
        printf( "%u", myArray[n] );

        if ( n < size-1 )
            printf( ", " );
    }
    printf( " }\n" );
}

Ada beberapa peringatan di atas; satu adalah yang UINT myArray[size];tidak langsung diinisialisasi pada deklarasi, namun blok kode berikutnya atau panggilan fungsi melakukan inisialisasi setiap elemen array ke nilai yang sama yang Anda inginkan. Peringatan lainnya adalah, Anda harus menulis initializing functionuntuk setiap typeAnda akan mendukung dan Anda juga harus memodifikasi printArray()fungsi untuk mendukung jenis-jenis tersebut.


Anda dapat mencoba kode ini dengan pengompil online yang ditemukan di sini .

Francis Cugler
sumber
0

Untuk inisialisasi tertunda (mis. Inisialisasi konstruktor anggota kelas) pertimbangkan:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;
nikc
sumber
0

Saya tahu pertanyaan asli secara eksplisit menyebutkan C dan bukan C ++, tetapi jika Anda (seperti saya) datang ke sini mencari solusi untuk array C ++, berikut ini adalah trik yang rapi:

Jika kompiler Anda mendukung ekspresi lipat , Anda dapat menggunakan templat sulap dan std::index_sequenceuntuk menghasilkan daftar penginisialisasi dengan nilai yang Anda inginkan. Dan Anda dapat meratakannya constexprdan merasa seperti bos:

#include <array>

/// [3]
/// This functions's only purpose is to ignore the index given as the second
/// template argument and to always produce the value passed in.
template<class T, size_t /*ignored*/>
constexpr T identity_func(const T& value) {
    return value;
}

/// [2]
/// At this point, we have a list of indices that we can unfold
/// into an initializer list using the `identity_func` above.
template<class T, size_t... Indices>
constexpr std::array<T, sizeof...(Indices)>
make_array_of_impl(const T& value, std::index_sequence<Indices...>) {
    return {identity_func<T, Indices>(value)...};
}

/// [1]
/// This is the user-facing function.
/// The template arguments are swapped compared to the order used
/// for std::array, this way we can let the compiler infer the type
/// from the given value but still define it explicitly if we want to.
template<size_t Size, class T>
constexpr std::array<T, Size> 
make_array_of(const T& value) {
    using Indices = std::make_index_sequence<Size>;
    return make_array_of_impl(value, Indices{});
}

// std::array<int, 4>{42, 42, 42, 42}
constexpr auto test_array = make_array_of<4/*, int*/>(42);
static_assert(test_array[0] == 42);
static_assert(test_array[1] == 42);
static_assert(test_array[2] == 42);
static_assert(test_array[3] == 42);
// static_assert(test_array[4] == 42); out of bounds

Anda dapat melihat kode di tempat kerja (di Wandbox)

Clemens Sielaff
sumber
-1

Saya tidak melihat persyaratan dalam pertanyaan, jadi solusinya harus generik: inisialisasi array multidimensi mungkin tidak ditentukan dibangun dari elemen struktur mungkin tidak ditentukan dengan nilai anggota awal:

#include <string.h> 

void array_init( void *start, size_t element_size, size_t elements, void *initval ){
  memcpy(        start,              initval, element_size              );
  memcpy( (char*)start+element_size, start,   element_size*(elements-1) );
}

// testing
#include <stdio.h> 

struct s {
  int a;
  char b;
} array[2][3], init;

int main(){
  init = (struct s){.a = 3, .b = 'x'};
  array_init( array, sizeof(array[0][0]), 2*3, &init );

  for( int i=0; i<2; i++ )
    for( int j=0; j<3; j++ )
      printf("array[%i][%i].a = %i .b = '%c'\n",i,j,array[i][j].a,array[i][j].b);
}

Hasil:

array[0][0].a = 3 .b = 'x'
array[0][1].a = 3 .b = 'x'
array[0][2].a = 3 .b = 'x'
array[1][0].a = 3 .b = 'x'
array[1][1].a = 3 .b = 'x'
array[1][2].a = 3 .b = 'x'

EDIT: start+element_sizediubah menjadi(char*)start+element_size

sambowry
sumber
1
Saya ragu apakah ini solusi atau tidak. Saya tidak yakin apakah sizeof(void)ini valid.
Chris Lutz
3
Itu tidak bekerja. Hanya dua yang pertama diinisialisasi, sisanya semua tidak diinisialisasi. Saya menggunakan GCC 4.0 pada Mac OS X 10.4.
dreamlax
Ini memunculkan perilaku yang tidak terdefinisi karena sumber data pada memcpy()tumpang tindih kedua dengan ruang tujuan. Dengan implementasi naif dari memcpy(), itu bisa berfungsi tetapi tidak diperlukan bahwa sistem membuatnya berfungsi.
Jonathan Leffler
-1

Kembali pada hari itu (dan saya tidak mengatakan itu ide yang baik), kami akan menetapkan elemen pertama dan kemudian:

memcpy (&element [1], &element [0], sizeof (element)-sizeof (element [0]);

Bahkan tidak yakin itu akan berfungsi lagi (yang akan tergantung pada implementasi memcpy) tetapi ia bekerja dengan berulang kali menyalin elemen awal ke yang berikutnya - bahkan berfungsi untuk susunan struktur.

Mike
sumber
Itu tidak akan bekerja dengan andal. IMHO, Standar seharusnya menyediakan fungsi-fungsi yang seperti memcpytetapi perintah penyalinan bottom-up atau top-down yang ditentukan jika tumpang tindih, tetapi tidak.
supercat
Seperti yang saya katakan, itu hanya sesuatu yang kami lakukan yang tidak akan bekerja dengan baik tetapi, saat itu, kami lebih fokus pada efisiensi daripada menghindari fitur yang tidak terdokumentasi. Meskipun lebih efisien untuk menyalin memori ke depan, tidak ada dalam spesifikasi untuk mengatakan itu tidak dapat menyalinnya ke belakang, dalam urutan acak atau membaginya di beberapa utas. memmove () menyediakan kemampuan untuk menyalin tanpa bentrok.
Mike
Ini sama dengan kode di jawaban lain - dan cacat. Menggunakannya memmove()tidak membuatnya bekerja.
Jonathan Leffler
-2

Jika Anda maksud secara paralel, saya pikir operator koma ketika digunakan bersama dengan ekspresi dapat melakukan itu:

a[1]=1, a[2]=2, ..., a[indexSize]; 

atau jika Anda maksud dalam satu konstruksi, Anda bisa melakukannya dalam for for:

for(int index = 0, value = 10; index < sizeof(array)/sizeof(array[0]); index++, value--)
  array[index] = index;

// Perhatikan operator koma dalam daftar argumen bukan operator paralel yang dijelaskan di atas;

Anda dapat menginisialisasi deklarasi array:

array[] = {1, 2, 3, 4, 5};

Anda dapat melakukan panggilan ke malloc / calloc / sbrk / mengalokasikan / dll untuk mengalokasikan wilayah penyimpanan yang tetap ke objek:

int *array = malloc(sizeof(int)*numberOfListElements/Indexes);

dan akses anggota dengan:

*(array + index)

Dll

pchelper4
sumber
Operator koma secara nominal menjamin evaluasi dari kiri ke kanan. Jika tidak ada efek samping dalam ekspresi, maka dimungkinkan untuk memparalelkan operasi, tetapi tidak biasa bagi kompiler untuk melakukannya.
Jonathan Leffler