Hoe initialiseer ik alle leden van een array met dezelfde waarde?

Ik heb een grote array in C(niet C++als dat een verschil maakt). Ik wil alle leden met dezelfde waarde initialiseren.

Ik zou zweren dat ik ooit een eenvoudige manier wist om dit te doen. Ik zou in mijn geval memset()kunnen gebruiken, maar is er geen manier om dit te doen die rechtstreeks in de C-syntaxis is ingebouwd?


Antwoord 1, autoriteit 100%

Tenzij die waarde 0 is (in dat geval kunt u een deel van de initialisatie weglaten)
en de bijbehorende elementen worden geïnitialiseerd op 0), is er geen gemakkelijke manier.

Vergeet de voor de hand liggende oplossing echter niet:

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

Elementen met ontbrekende waarden worden geïnitialiseerd op 0:

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

Dus dit zal alle elementen naar 0 initialiseren:

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

In C++ zal een lege initialisatielijst ook elk element naar 0 initialiseren.
Dit is niet toegestaanmet C:

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

Houd er rekening mee dat objecten met een statische opslagduur worden geïnitialiseerd op 0 als nee
initialisatie is opgegeven:

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

En die “0” betekent niet noodzakelijkerwijs “alle-bits-nul”, dus het gebruik van het bovenstaande is
beter en draagbaarder dan memset(). (Drijvende-kommawaarden zijn
geïnitialiseerd op +0, verwijzingen naar null-waarde, enz.)


Antwoord 2, autoriteit 31%

Als uw compiler GCC is, kunt u de volgende syntaxis gebruiken:

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

Bekijk de gedetailleerde beschrijving:
http://gcc.gnu.org/onlinedocs/gcc -4.1.2/gcc/Designated-Inits.html


Antwoord 3, autoriteit 14%

Voor het statisch initialiseren van een grote array met dezelfde waarde, zonder meerdere keren kopiëren en plakken, kunt u macro’s gebruiken:

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

Als u de waarde moet wijzigen, hoeft u de vervanging maar op één plaats uit te voeren.

Bewerken: mogelijke nuttige extensies

(met dank aan Jonathan Leffler)

Je kunt dit gemakkelijk generaliseren met:

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

Een variant kan worden gemaakt met:

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

die werkt met structuren of samengestelde arrays.

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

macronamen zijn bespreekbaar.


Antwoord 4, autoriteit 5%

Als u er zeker van wilt zijn dat elk lid van de array expliciet wordt geïnitialiseerd, hoeft u alleen de dimensie uit de declaratie weg te laten:

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

De compiler zal de dimensie afleiden uit de initialisatielijst. Helaas kan voor multidimensionale arrays alleen de buitenste dimensie worden weggelaten:

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

is OK, maar

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

is niet.


Antwoord 5, autoriteit 4%

Ik zag een code die deze syntaxis gebruikte:

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

Het wordt vooral handig als je een array maakt die enums als index gebruikt:

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

Dit houdt de zaken op orde, zelfs als u enkele van de enum-waarden niet in de juiste volgorde schrijft.

Meer over deze techniek is te vinden hieren hier.


Antwoord 6, Autoriteit 2%

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

Ik denk dat dit beter is dan

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

Incase de grootte van de arraywijzigingen.


Antwoord 7

U kunt het hele statische initialiser ding doen zoals hierboven beschreven, maar het kan een echte bummer zijn wanneer uw array-grootte verandert (wanneer uw array embiggent, als u niet de juiste extra initializers toevoegt, krijgt u afval).

Memet geeft u een runtime-hit voor het doen van het werk, maar er is geen coderingsgrootte gedaan die goed is gedaan, is immuun voor veranderingen op de array-formaat. Ik zou deze oplossing in bijna alle gevallen gebruiken wanneer de array groter is dan, zeg maar een paar dozijn elementen.

Als het erg belangrijk was dat de array statisch werd gedeclareerd, zou ik een programma schrijven om het programma voor mij te schrijven en het deel uit te maken van het bouwproces.


Antwoord 8

Hier is een andere manier:

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

Zie:

C-extensions

aangewezen ingenomen

Stel vervolgens de vraag: Wanneer kan men C-extensies gebruiken?

Het hierboven bovenstaande code bevindt zich in een ingesloten systeem en zal het licht nooit van een andere compiler zien.


Antwoord 9

Voor het initialiseren van ‘normale’ gegevenstypen (zoals int-arrays), kunt u de haakjesnotatie gebruiken, maar deze zal de waarden na de laatste op nul stellen als er nog ruimte in de array is:

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

Antwoord 10

Een enigszins ironisch antwoord; schrijf de verklaring

array = initial_value

in uw favoriete array-compatibele taal (de mijne is Fortran, maar er zijn vele andere), en koppel deze aan uw C-code. Je zou het waarschijnlijk willen afronden als een externe functie.


Antwoord 11

Als de array toevallig int is of iets met de grootte van int of de grootte van je mem-patroon past exacte tijden in een int (dwz allemaal nullen of 0xA5A5A5A5), dan is de beste manier om memset().

Roep anders memcpy() aan in een lus die de index verplaatst.


Antwoord 12

Er is een snelle manier om een array van elk type met een bepaalde waarde te initialiseren. Het werkt heel goed met grote arrays. Algoritme is als volgt:

  • initialiseer het eerste element van de array (gebruikelijke manier)
  • kopieer een deel dat is ingesteld naar een deel dat niet is ingesteld, waarbij de grootte wordt verdubbeld bij elke volgende kopieerbewerking

Voor 1 000 000elementen intarray is het 4 keer sneller dan normale lusinitialisatie (i5, 2 cores, 2,3 GHz, 4GiB geheugen, 64 bits):

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

Antwoord 13

Ik weet de oorspronkelijke vraag expliciet vermeldt C en niet C++, maar als u (zoals ik) hier bent gekomen op zoek naar een oplossing voor C++ -arrays, hier is een nette truc:

Als uw compiler vouwuitdrukkingen , kunt u sjabloonmagie en std::index_sequenceom een ​​initializerlijst te genereren met de gewenste waarde. En je kunt zelfs constexprIT en voelen als een baas:

#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

U kunt een kijkje nemen op de -code op het werk (bij Wandbox)


Antwoord 14

  1. Als uw array wordt gedeclareerd als statische of wereldwijde, alle elementen
    In de array is al standaard standaardwaarde 0.
  2. Sommige compilers SET ARRY’S DE STANDELING TOT 0 IN DEBUG-modus.
  3. Het is eenvoudig in te stellen standaard op 0:
    int array [10] = {0};
  4. Voor andere waarden hebt u Memet () of lus gebruikt;

Voorbeeld:
int array [10];
Memet (array, -1, 10 * size van (INT));


Antwoord 15

int array [1024] = {[0 … 1023] = 5}; Naarmate het bovenstaande goed werkt, maar zorg ervoor dat er geen spaties tussen de … Dots


Antwoord 16

Niemand heeft de indexvolgorde genoemd om toegang te krijgen tot de elementen van de geïnitialiseerde array. Mijn voorbeeldcode geeft er een illustratief voorbeeld aan.

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

De uitvoer is:

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

Antwoord 17

Door alle chatter doorsnijden, is het korte antwoord dat als u optimalisatie inschakelt bij compileertijd, u niet beter doet dan dit:

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

Toegevoegd bonus: de code is eigenlijk leesbaar 🙂


Antwoord 18

Ik weet dat de gebruiker Tarskideze vraag op dezelfde manier beantwoordde, maar ik voegde nog een paar details toe. Vergeef een deel van mijn C want ik ben een beetje roestig aan het omdat ik meer geneigd ben om C++ te willen gebruiken, maar hier gaat het.


Als u de grootte van de array van vóór de tijd kent …

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

Er zijn een paar voorbehoud boven; Eén is dat UINT myArray[size];wordt niet rechtstreeks geïnitialiseerd op de aangifte, maar het zeer volgende codeblok of functieoproep initialiseert elk element van de array op dezelfde waarde die u wilt. De andere cèneet is, u zou een initializing functionvoor elk typeU zal ondersteunen en u zou ook de printArray()functie om die typen te ondersteunen.


U kunt deze code proberen met een online-compries gevonden hier .


Antwoord 19

Voor vertraging initialisatie (d.w.z. Class Lid Constructor Initialisation) Overweeg:

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

Antwoord 20

Als de grootte van de array van tevoren bekend is, zou men een Boost-preprocessor C_ARRAY_INITIALIZE-macro kunnen gebruiken om het vuile werk voor u te doen:

#include <boost/preprocessor/repetition/enum.hpp>
#define C_ARRAY_ELEMENT(z, index, name) name[index]
#define C_ARRAY_EXPAND(name,size) BOOST_PP_ENUM(size,C_ARRAY_ELEMENT,name)
#define C_ARRAY_VALUE(z, index, value) value
#define C_ARRAY_INITIALIZE(value,size) BOOST_PP_ENUM(size,C_ARRAY_VALUE,value)

Antwoord 21

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

Het geeft de o/p 5 5 5 5 5 5 …… tot de grootte van de hele array


Antwoord 22

methode 1:

int a[5] = {3,3,3,3,3}; 

formele initialisatietechniek.

methode 2:

int a[100] = {0};

maar het is de moeite waard om op te merken dat

int a[10] = {1}; 

initialiseert niet alle waarden naar 1

deze manier van initialiseren exclusief voor 0

als je het gewoon doet

int a[100];

sommige compilers hebben de neiging om afvalwaarde te gebruiken, vandaar dat dit altijd de voorkeur heeft

int a[1000] = {0};

Antwoord 23

Initialiseren met nullen –

 char arr[1000] = { 0 };

Het is beter om te doen met de normale “for loop” voor andere initialen dan 0.

 char arr[1000];
  for(int i=0; i<arr.size(); i++){
     arr[i] = 'A';
  }

Antwoord 24

Ik zie geen vereisten in de vraag, dus de oplossing moet generiek zijn: initialisatie van een niet-gespecificeerde mogelijk multidimensionale array opgebouwd uit niet-gespecificeerde mogelijke structuurelementen met een initiële lidwaarde:

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

Resultaat:

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_sizegewijzigd in (char*)start+element_size


Antwoord 25

Vroeger (en ik zeg niet dat het een goed idee is), zouden we het eerste element instellen en dan:

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

Zelfs niet zeker of het meer zou werken (dat zou afhangen van de implementatie van Memcpy), maar het werkt door herhaaldelijk het initiële element naar de volgende te kopiëren – werkt zelfs voor arrays van structuren.

Other episodes