Jak inicializovat všechny členy pole na stejnou hodnotu?

hlasů
770

Mám velké pole v C (ne C ++, pokud to je rozdíl). Chci inicializovat všechny členy na stejnou hodnotu. Mohl bych přísahat Znal jsem kdysi jednoduchý způsob, jak toho dosáhnout. Mohl bych použít memset()v mém případě, ale neexistuje způsob, jak to, že je postaven přímo do syntaxe C dělat?

Položena 14/10/2008 v 14:13
zdroj uživatelem
V jiných jazycích...                            


23 odpovědí

hlasů
1k

Není-li tato hodnota je 0 (v takovém případě můžete vynechat některé části inicializátor a odpovídající prvky budou inicializovány na 0), neexistuje žádný jednoduchý způsob.

Nepřehlédněte jasné řešení, i když:

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

Prvky s chybějícími hodnotami bude inicializován na 0:

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

Takže to bude inicializovat všechny prvky na 0:

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

V jazyce C ++, prázdný seznam inicializační také inicializovat každý prvek na hodnotu 0. To není povoleno s C:

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

Uvědomte si, že objekty se statickým trvání skladování se inicializuje na 0, pokud není stanoveno Inicializátor:

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

A že „0“ nemusí nutně znamenat „všechny bity nula“, takže za použití výše uvedené je lepší a přenosný než memset (). (Hodnoty s plovoucí desetinnou čárkou bude inicializována +0, odkazy na null hodnota, atd.)

Odpovězeno 14/10/2008 v 14:17
zdroj uživatelem

hlasů
342

Pokud váš kompilátor GCC, můžete použít následující syntaxi:

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

Podívejte se na podrobný popis: http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html

Odpovězeno 16/10/2008 v 08:38
zdroj uživatelem

hlasů
159

Pro staticky inicializaci velké pole se stejnou hodnotou, bez vícenásobného kopírování a vkládání, můžete využít makra:

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

Potřebujete-li změnit hodnotu, budete muset provést výměnu pouze na jednom místě.

Edit: možná užitečné rozšíření

(se svolením Jonathan Leffler )

Můžete snadno zobecnit to s:

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

Varianta může být vytvořen za použití:

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

, který pracuje se strukturami nebo krmných pole.

#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 jména jsou obchodovatelné.

Odpovězeno 14/10/2009 v 11:27
zdroj uživatelem

hlasů
59

Chcete-li zajistit, aby každý člen pole je výslovně inicializován, stačí vynechat rozměr z prohlášení:

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

Kompilátor odvodit rozměr ze seznamu Inicializátor. Bohužel, pro vícerozměrných polí pouze vnější rozměr může být vynechán:

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

je v pořádku, ale

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

není.

Odpovězeno 14/10/2008 v 19:30
zdroj uživatelem

hlasů
44

Viděl jsem nějaký kód, který používal tuto syntaxi:

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

V případě, že je obzvláště užitečné, pokud je děláte pole, které používá výčty jako index:

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

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

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

To udržuje pořádek, a to i pokud jste náhodou psát některé z výčtu hodnot mimo provoz.

Více informací o této technice lze nalézt zde a zde .

Odpovězeno 21/03/2012 v 22:02
zdroj uživatelem

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

Myslím, že to je lepší než

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

zapouzdřit velikost změny pole.

Odpovězeno 14/10/2008 v 14:34
zdroj uživatelem

hlasů
11

Můžete to udělat celou statickou inicializátor věc, jak je uvedeno výše, ale to může být skutečný průšvih, když vaše změny velikosti pole (je-li vaše pole embiggens, pokud nechcete přidat příslušná další inicializátory dostanete odpadky).

memset vám runtime hit za dělat práci, ale ne hit velikost kódu se dobře, je imunní vůči změnám velikosti pole. Bych použít toto řešení téměř ve všech případech, kdy pole byla větší než, řekněme, několik desítek prvků.

Kdyby to bylo opravdu důležité, aby byla sestava staticky prohlášen, tak bych napsat program, napsat program pro mě a učinit z něj součást procesu sestavení.

Odpovězeno 14/10/2008 v 14:29
zdroj uživatelem

hlasů
8

Tady je další způsob, jak:

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

Vidět:

C-Extensions

Prostor inits

Pak položit otázku: Kdy můžeme použít rozšíření C?

Ukázkový kód výše je vestavěný systém a nikdy vidět světlo z jiného kompilátoru.

Odpovězeno 14/10/2008 v 23:12
zdroj uživatelem

hlasů
5

Mírně jazyk-in-tváře odpověď; napište příkaz

array = initial_value

ve svém oblíbeném poli-schopný jazyk (moje je Fortran, ale existuje mnoho dalších), a propojit ji do svého C kód. Vy byste asi chtěli zabalit tak, aby byl externí funkce.

Odpovězeno 14/10/2009 v 11:33
zdroj uživatelem

hlasů
5

Pro inicializaci ‚normální‘ datové typy (jako int pole), můžete použít notaci držák, ale to bude nula hodnoty po posledním případě, že je stále prostor v poli:

// put values 1-8, then two zeroes
int list[10] = {1,2,3,4,5,6,7,8};
Odpovězeno 14/10/2008 v 14:17
zdroj uživatelem

hlasů
4

V případě, že pole se stane být int nebo něco s velikostí int nebo velikosti vašeho MEM-vzor je zapadá přesné časy do int (tedy všechny nuly nebo 0xA5A5A5A5), nejlepší způsob, jak je použít memset () .

V opačném případě volání memcpy () ve smyčce pohybující indexu.

Odpovězeno 14/10/2008 v 14:59
zdroj uživatelem

hlasů
3

K dispozici je rychlý způsob, jak inicializovat pole libovolného typu s danou hodnotou. To funguje velmi dobře s velkými poli. Algoritmus je následující:

  • inicializaci prvního prvku pole (obvyklým způsobem)
  • zkopírovat část, která byla nastavena do části, která nebyla nastavena, zdvojnásobení velikosti s každou další operace kopírování

Pro 1 000 000prvky intpole je 4 krát rychlejší než pravidelné inicializaci smyčky (i5, 2 jádra, 2.3 GHz, 4GiB paměti, 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;
}
Odpovězeno 29/07/2015 v 00:17
zdroj uživatelem

hlasů
2

Nikdo se zmínil pořadí index pro přístup prvky inicializační pole. Můj příklad kódu dá názorný příklad k tomu.

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

Výstupem je:

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
Odpovězeno 06/02/2016 v 15:24
zdroj uživatelem

hlasů
2

Můžete použít memset funkci.

void *memset(void *array, int value, unsigned sizeofarray);
Odpovězeno 29/04/2012 v 05:28
zdroj uživatelem

hlasů
1

Řezání přes všechny klábosení, krátká odpověď je, že pokud zapnete optimalizace v době kompilace nebude dělat lépe než toto:

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

Bonus: kód je skutečně čitelný :)

Odpovězeno 05/11/2016 v 16:12
zdroj uživatelem

hlasů
1
  1. Pokud je vaše pole je deklarován jako statické nebo je globální, všechny prvky v poli již výchozí výchozí hodnotu 0.
  2. Některé kompilátory nastavené pole je výchozí na hodnotu 0 v režimu ladění.
  3. Je snadné nastavit výchozí až 0: int pole [10] = {0};
  4. Nicméně, pro jiné hodnoty, máte použití memset () nebo smyčky;

Příklad: int pole [10]; memset (pole, -1, 10 * sizeof (int));

Odpovězeno 29/07/2015 v 01:21
zdroj uživatelem

hlasů
0

Pokud máte na mysli zároveň si myslím, že operátor čárka při použití ve spojení s výrazem, může dělat, že:

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

nebo pokud máte na mysli v jednom konstruktu, jsi to mohl udělat, že v cyklu for:

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

// Všimněte si operátor čárka v seznamu argumentů není paralelní obsluha je popsáno výše;

Můžete inicializovat decleration pole:

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

Můžete volat na malloc / calloc / sbrk / alloca / etc přidělit pevnou oblast ukládání do objektu:

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

a přístup k členům podle:

*(array + index)

Atd.

Odpovězeno 17/10/2019 v 01:07
zdroj uživatelem

hlasů
0

Zpět v den (a neříkám, že je to dobrý nápad), bychom nastavit první prvek a potom:

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

Není si jistý, že to bude fungovat nic víc (to bude záviset na plnění memcpy), ale funguje to opakovaným kopírováním počátečního prvku k druhému - funguje i pro pole struktur.

Odpovězeno 14/01/2019 v 08:53
zdroj uživatelem

hlasů
0

Za opožděné inicializaci (tj člen konstruktoru inicializace třída) brát v úvahu:

int a[4];

unsigned int size = sizeof(a) / sizeof(a[0]);
for (unsigned int i = 0; i < size; i++)
  a[i] = 0;
Odpovězeno 19/10/2018 v 17:08
zdroj uživatelem

hlasů
0

Vím, že uživatel Tarskina tuto otázku podobným způsobem odpověděl, ale jsem přidal několik dalších detailů. Odpustit některé z mých C po dobu jsem trochu rezavý na to, protože jsem více nakloněn chtít využít C ++, ale tady to jde.


Pokud víte, že velikost pole dopředu ...

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

Existuje několik výhradami výše; člověk, který UINT myArray[size];není přímo inicializovat na prohlášení, ale hned druhý blok kódu nebo volání funkce dělá inicializuje každý prvek pole na stejnou hodnotu, kterou chcete. Druhou námitkou je, budete muset psát initializing functionpro každý typebudete podporovat a měli byste mít také upravit printArray()funkci podporovat tyto druhy.


Můžete zkusit tento kód s online complier našel zde .

Odpovězeno 28/01/2018 v 19:30
zdroj uživatelem

hlasů
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;
}

To dá O / P 5 5 5 5 5 5 ...... až do velikosti celé pole

Odpovězeno 26/10/2017 v 08:31
zdroj uživatelem

hlasů
-1

Vím, že původní otázka výslovně zmiňuje C a ne C ++, ale pokud sem přišli vy (jako já), kteří hledají řešení pro C ++ pole, tady je pěkný trik:

Pokud váš kompilátor podporuje složit výrazy , můžete použít šablony kouzlo a std::index_sequencepro generování seznamu Inicializátor s hodnotou, kterou chcete. A dokonce můžete constexprho a cítit se jako šéf:

#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

Můžete se podívat na kód v práci (v Wandbox)

Odpovězeno 13/02/2019 v 09:44
zdroj uživatelem

hlasů
-1

I vidět žádné požadavky v úvahu, takže řešení musí být generické: inicializace nespecifikované možná vícerozměrné poli postaveném z NS případně uspořádat prvky s počáteční člen hodnoty:

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

Výsledek:

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_sizezměněn na(char*)start+element_size

Odpovězeno 14/10/2009 v 00:40
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more