it-swarm-tr.com

Bir dizinin tüm üyelerini aynı değere nasıl başlatabilirim?

C büyük bir dizi var (eğer bir fark yaratıyorsa C++ değil). Tüm üyeleri aynı değerde başlatmak istiyorum. Yemin ederim bir zamanlar bunu yapmanın basit bir yolunu biliyordum. Benim durumumda memset() işlevini kullanabilirim, ancak bunu doğrudan C sözdizimine dahil etmenin bir yolu yok mu?

855
Matt

Bu değer 0 değilse (bu durumda, başlatıcının bir kısmını atlayabilirsiniz ve karşılık gelen öğeler 0 olarak başlatılır), kolay bir yol yoktur.

Yine de bariz çözümü göz ardı etmeyin:

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

Eksik değere sahip elemanlar 0 olarak başlatılır:

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

Bu, tüm öğeleri 0'a başlatacak:

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

C++ 'da boş bir başlatma listesi ayrıca her elemanı 0'a sıfırlar. Bu, izin verilmez C ile:

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

Hiçbir başlatıcı belirtilmezse statik saklama süresi olan nesnelerin 0 olarak başlatılacağını unutmayın:

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

Ve bu "0" mutlaka "hepsi-sıfır" anlamına gelmez, bu yüzden yukarıdakileri kullanmak memset () işlevinden daha iyi ve daha taşınabilirdir. (Kayan nokta değerleri +0, işaretçiler boş değer vb.

1172
aib

Derleyiciniz GCC ise, aşağıdaki sözdizimini kullanabilirsiniz:

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

Ayrıntılı açıklamaya göz atın: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html

364
qrdl

Aynı değerde büyük bir diziyi statik olarak başlatmak için, birden çok kopyala yapıştır kullanmadan makroları kullanabilirsiniz:

#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 };

Değeri değiştirmeniz gerekirse, değişimi yalnızca bir yerde yapmanız gerekir.

Düzenleme: olası faydalı uzantılar

( Jonathan Leffler’in izniyle )

Bunu kolayca genelleştirebilirsiniz:

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

Bir varyant kullanılarak oluşturulabilir:

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

bu yapılar veya bileşik dizileri ile çalışır.

#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) };

makro adları tartışılabilir. 

169
mouviciel

Dizinin her üyesinin açıkça başlatıldığından emin olmak istiyorsanız, boyuttan bildirimden kaçınmanız yeterlidir:

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

Derleyici, boyutlandırıcıyı başlatıcı listesinden çıkartacaktır. Ne yazık ki, çok boyutlu diziler için yalnızca en dıştaki boyut ihmal edilebilir:

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

tamam ama

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

değil.

61
Frank Szczerba

Bu sözdizimini kullanan bazı kodlar gördüm:

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

Özellikle kullanışlı hale geldiği yer, dizin olarak enums kullanan bir dizi yapıyorsanız:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

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

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

Enum değerlerinin bir kısmını sıra dışı yazsanız bile, bu işleri düzenli tutar.

Bu teknik hakkında daha fazla bilgi here ve here 'dır.

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

Bence bu daha iyi

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

dizi değişikliklerinin boyutunu inase.

21
Tarski

Tüm statik başlatıcıyı yukarıda ayrıntılı olarak yapabilirsiniz, ancak dizi boyutunuz değiştiğinde gerçek bir serseri olabilir (dizi yerleştirildiğinde, uygun ekstra başlatıcıları eklemezseniz çöp alırsınız).

memset, işi yapmak için size bir çalışma zamanı isabeti verir, ancak doğru şekilde yapılan hiçbir kod boyutu, dizi boyutu değişikliklerine karşı bağışıklık kazanmaz. Bu çözümü, neredeyse her durumda, dizinin birkaç düzine öğeden daha büyük olduğu durumlarda kullanırdım.

Dizinin statik olarak bildirilmesi gerçekten önemliyse, programı benim için yazmak ve derleme sürecinin bir parçası yapmak için bir program yazardım.

11
plinth

İşte başka bir yol:

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},
};

Görmek:

C Eklentileri

Belirlenmiş inits

Sonra şu soruyu sorun: Bir C uzantısını ne zaman kullanabilir?

Yukarıdaki kod örneği gömülü bir sistemdedir ve hiçbir zaman başka bir derleyiciden gelen ışığı görmez. 

7
humble_guru

Hafif bir yanak dili cevap; ifadeyi yaz

array = initial_value

en sevdiğiniz dizi yetenekli dilinizde (benimki Fortran, fakat daha birçokları var) ve C kodunuzla bağlantı kurun. Muhtemelen harici bir fonksiyon olarak sarmak istersiniz.

5

'Normal' veri türlerini (int dizileri gibi) başlatmak için, parantez notasyonunu kullanabilirsiniz, ancak dizide hala boşluk varsa, sondan sonra değerleri sıfırlar:

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

Dizi int ise veya int büyüklüğünde bir şey olursa veya mem şablonunuzun büyüklüğü bir int'ye tam olarak uyuyorsa (yani tüm sıfırlar veya 0xA5A5A5A5), en iyi yol memset () komutunu kullanmaktır.

Aksi takdirde, memcpy () 'yi indeksi hareket ettiren bir döngüde çağırın.

4
ddimitrov

Herhangi bir türdeki diziyi verilen değerle başlatmanın hızlı bir yolu var. Büyük dizilerle çok iyi çalışır. Algoritma şöyledir:

  • dizinin ilk elemanını başlat (normal yol)
  • bir sonraki kopya işleminde boyutu iki katına çıkararak, ayarlanmamış kısma yerleştirilmiş olan kısmı kopyalayın

1 000 000 elements int dizisi, normal döngü başlatma işleminden 4 kat daha hızlıdır (i5, 2 çekirdek, 2.3 GHz, 4GiB bellek, 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;
}
3
Maciej
  1. Diziniz statik olarak bildirilmişse veya global ise, dizideki tüm öğeler. zaten dizinin varsayılan varsayılan değeri 0'dır.
  2. Bazı derleyiciler, hata ayıklama modunda dizinin varsayılan değerini 0 olarak ayarlar. 
  3. Varsayılan değeri 0'a ayarlamak kolaydır: İnt array [10] = {0}; 
  4. Ancak, diğer değerler için memset () veya loop kullandınız;

örnek: int dizi [10]; memset (dizi, -1, 10 * sizeof (int));

1
Hannah Zhang

Tüm konuşmayı keserek, kısa cevap, derleme zamanında optimizasyonu açarsanız bundan daha iyisini yapmayacağınızdır 

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

Eklenen bonus: kod aslında okunaklı :)

1
JWDN

Başlatılan dizinin öğelerine erişmek için dizin sırasından kimse bahsetmedi. Örnek kodum buna açıklayıcı bir örnek verecektir.

#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;
}

Çıktı:

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
1
hkBattousai

Gecikmeli başlatma için (yani, sınıf üyesi yapıcı başlatma) şunları göz önünde bulundurun

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;
0
nikc
#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;
}

O/p 5 5 5 5 5 5 ...... dizisini tüm boyutuna kadar verecek

0
Dadhich Sourav

Güne döndüm (ve bunun iyi bir fikir olduğunu söylemiyorum), ilk elemanı belirledik ve sonra:

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

Artık işe yarayacağından emin bile değil (memcpy uygulamasına bağlı olacaktır), ancak ilk öğeyi art arda kopyalayarak çalışır - hatta yapı dizileri için bile çalışır.

0
Mike

Tarski kullanıcısının bu soruyu benzer şekilde cevapladığını biliyorum, ancak birkaç ayrıntı daha ekledim. C++ 'ı biraz affet çünkü biraz paslanmışım çünkü C++' ı kullanmak istemeye meyilliyim, ama işte başlıyor.


Zamanın öncesindeki dizinin boyutunu biliyorsanız ...

#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" );
}

Yukarıda birkaç uyarı var; Birincisi, UINT myArray[size];, bildirimin üzerine doğrudan başlatılmadı, ancak bir sonraki kod bloğu veya işlev çağrısı, dizinin her öğesini istediğiniz değerle başlatıyor. Diğer bir uyarı, destekleyeceğiniz her type için bir initializing function yazmanız gerekecek ve ayrıca bu türleri desteklemek için printArray() işlevini değiştirmeniz gerekecektir.


Bu kodu, here dizininde bulunan çevrimiçi bir karşılaştırıcıyla deneyebilirsiniz.

0
Francis Cugler