programing

어레이의 모든 멤버를 동일한 값으로 초기화하려면 어떻게 해야 합니까?

goodcopy 2022. 7. 5. 00:22
반응형

어레이의 모든 멤버를 동일한 값으로 초기화하려면 어떻게 해야 합니까?

C에 큰 어레이가 있습니다(차이가 있다면 C++가 아닙니다).같은 값의 멤버를 모두 초기화합니다.

맹세컨데 난 이걸 하는 간단한 방법을 알고 있었어.나는 할 수 있다memset()저 같은 경우에는 C 구문에 직접 내장된 방법이 없을까요?

이 값이 0이 아니면(이 경우 이니셜라이저의 일부를 생략할 수 있고 대응하는 요소가 0으로 초기화됩니다), 쉬운 방법은 없습니다.

단, 다음과 같은 명백한 해결책을 간과해서는 안 됩니다.

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

결측값이 있는 요소는 0으로 초기화됩니다.

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

그러면 모든 요소가 0으로 초기화됩니다.

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

C++에서는 빈 초기화 리스트도 모든 요소를 0으로 초기화합니다.이것은 C:에서는 허용되지 않습니다.

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

initializer가 지정되지 않은 경우 정적 스토리지 기간이 있는 개체가 0으로 초기화됩니다.

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

그리고 "0"은 반드시 "모든 비트 제로"를 의미하는 것은 아니기 때문에 위의 것을 사용하는 것이 memset()보다 더 좋고 휴대성이 좋습니다.(부동소수점 값은 +0으로 초기화되며 null 값으로 포인터 등이 됩니다.)

컴파일러가 GCC인 경우 다음 "GNU 확장" 구문을 사용할 수 있습니다.

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

자세한 것은, http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html 를 참조해 주세요.

복수의 카피 페이스트 없이, 같은 값의 대규모 어레이를 정적으로 초기화하는 경우는, 다음의 매크로를 사용할 수 있습니다.

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

값을 변경해야 할 경우 한 곳에서만 교체해야 합니다.

편집: 가능한 유용한 확장자

(조나단 레플러의 기도)

다음과 같은 방법으로 이를 쉽게 일반화할 수 있습니다.

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

배리언트는, 다음의 방법으로 작성할 수 있습니다.

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

구조체 또는 복합 어레이에서 작동합니다.

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

매크로명은 네고시에이트 가능합니다.

다음 구문을 사용하는 코드를 발견했습니다.

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

인덱스로 enum을 사용하는 배열을 만드는 경우 특히 유용합니다.

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

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

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

이렇게 하면 일부 열거값을 잘못 쓴 경우에도 순서가 유지됩니다.

이 기술에 대한 자세한 내용은 여기와 여기를 참조하십시오.

원래 질문에서 C++가 아닌 C가 언급되어 있는 것은 알고 있습니다만, (저와 같은) C++ 어레이의 솔루션을 찾고 있다면, 다음과 같은 요령이 있습니다.

컴파일러가 폴드 표현을 지원하는 경우 템플릿 매직과std::index_sequence원하는 값을 가진 이니셜라이저 목록을 생성합니다. 당신은 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」constexpr상사처럼 느껴져

#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

직장에서 코드를 볼 수 있습니다(Wandbox).

int array [ ]= { [ 0 ...1023] = 5}; 위의 작업은 정상적으로 수행되지만 ...개의 점 사이에 공백이 없어야 합니다.

  1. 어레이가 정적 또는 전역으로 선언된 경우 어레이의 모든 요소는 이미 기본값 0을 가집니다.
  2. 일부 컴파일러는 디버깅모드에서 어레이 기본값을 0으로 설정합니다.
  3. 기본값을 0: int array[10] = {0}으로 설정하는 것은 쉽습니다.
  4. 단, 다른 값에서는 memset() 또는 loop을 사용합니다.

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

약간 빈정거리는 대답; 진술서를 써라.

array = initial_value

마음에 드는 어레이 대응 언어(저는 Fortran이지만, 그 외 많은 언어)로 C 코드에 링크합니다.외부 기능으로 마무리하는 것이 좋습니다.

0으로 초기화하려면 -

  char arr[1000] = { 0 };

0 이외의 초기화에 대해서는, 통상의 「for loop」을 사용하는 것이 좋습니다.

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

배열의 모든 멤버가 명시적으로 초기화되도록 하려면 선언에서 차원을 생략하십시오.

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

컴파일러는 이니셜라이저 목록에서 치수를 추론합니다.안타깝게도 다차원 배열의 경우 가장 바깥쪽 치수만 생략할 수 있습니다.

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

괜찮지만

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

그렇지 않습니다.

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

이게 더 좋은 것 같아요

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

어레이의 크기가 변경될 수 있습니다.

는 그 .Tarski이 질문에 비슷한 대답을 했지만, 몇 가지 세부 사항을 추가했습니다.C++를 사용하고 싶은 경향이 있기 때문에, 조금 녹슬어 있기 때문에, C의 일부를 용서해 주세요.


어레이 크기를 미리 알고 있다면...

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

몇가지 경고에 우선하도록 해라;하나는 위에주의사항이 있습니다 가지 몇 있다.하나는UINT myArray[size];직접 선언에 초기화되지 않은가, 하지만 다음 코드 블록이나 함수 호출이 배열의 원하는 같은 값으로 각 요소를 초기화한다.는 선언 시 직접 초기화되지 않지만 바로 다음 코드 블록 또는 함수 호출에서는 어레이의 각 요소를 원하는 값으로 초기화합니다.다른 단서 조항, 여러분은또 다른 경고는,당신이 그 정보를을 할 것이라는 겁니다.initializing function각 각각에 대해서에type당신은, 당신은지원하게 될 것이며, 또한 이 기능을 수정해야 할 것입니다를 수정할 수 있는 것을 지원할 것이다.printArray()기능 그러한 유형을 지원하기 위해.이러한 타입을 서포트합니다.


여기 온라인 컴파일러에서 이 코드를 사용해 볼 수 있습니다.

지연된 초기화(즉, 클래스 멤버컨스트럭터 초기화)의 경우 다음을 고려하십시오.

int a[4];

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

어레이의 크기를 미리 알고 있는 경우 Boost 프리프로세서 C_ARRAY_INITIALIZE 매크로를 사용하여 지저분한 작업을 수행할 수 있습니다.

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

또 다른 방법은 다음과 같습니다.

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

참조:

C-확장

지정 단위

그런 다음 다음과 같은 질문을 합니다.언제 C 내선번호를 사용할 수 있습니까?

위의 코드 샘플은 임베디드 시스템에 포함되어 있어 다른 컴파일러에서 빛을 볼 수 없습니다.

모든 유형의 배열을 지정된 값으로 빠르게 초기화할 수 있습니다.대규모 어레이에서 매우 잘 작동합니다.알고리즘은 다음과 같습니다.

  • 배열의 첫 번째 요소를 초기화합니다(반복 방식).
  • 설정되지 않은 부분으로 설정된 복사 부품, 다음 복사 작업을 수행할 때마다 크기가 두 배로 증가합니다.

위해서1 000 000요소들int정열은 4배나 빠른 정기적인 루프 초기화(i5, 2코어, 2.3GHz,4GiB 기억, 64비트)보다:.

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

int 배열과 같은 '일반' 데이터 유형을 초기화하는 경우 괄호 표기법을 사용할 수 있지만 배열에 공간이 남아 있으면 마지막 뒤에 값이 0이 됩니다.

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

어레이가 int 사이즈 또는 mem-pattern 사이즈를 가진 int 또는 그 어떤 것이 우연히 int에 정확한 시간(즉, 모두 0 또는 0xA5)을 가진 경우A5A5A5)의 가장 좋은 방법은 memset()을 사용하는 것입니다.

그렇지 않으면 인덱스를 이동하는 루프에서 memcpy()를 호출합니다.

위에서 설명한 바와 같이 정적 이니셜라이저 전체를 수행할 수 있지만 어레이 크기가 변경되면 매우 곤란해질 수 있습니다(어레이가 확장되면 적절한 이니셜라이저를 추가하지 않으면 가비지가 됩니다).

memset은 작업을 수행하기 위한 런타임 히트를 제공하지만 올바르게 수행된 코드 크기는 어레이 크기 변경에 영향을 받지 않습니다.어레이가 수십 개의 요소보다 큰 경우에는 거의 모든 경우에 이 솔루션을 사용합니다.

어레이를 정적으로 선언하는 것이 정말 중요한 경우 프로그램을 작성하여 빌드 프로세스의 일부로 만들 수 있습니다.

아무도 초기화된 배열의 요소에 액세스하기 위한 인덱스 순서를 언급하지 않았습니다.나의 예 코드는 그것에 대한 예시를 줄 것이다.

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

출력은 다음과 같습니다.

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

모든 대화를 요약하면 컴파일 시 최적화를 활성화하면 다음과 같은 효과를 얻을 수 없습니다.

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

추가 보너스: 코드를 실제로 읽을 수 있습니다. : )

#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 ......가 됩니다.

질문에는 요건이 없습니다.따라서 해결책은 범용성이 있어야 합니다.즉, 초기 멤버 값을 가진 미지정 가능한 구조 요소에서 구축되는 미지정 가능한 다차원 배열의 초기화입니다.

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

결과:

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'

편집:편집:start+element_size로로 바뀌변경되었다(char*)start+element_size

옛날에는 (좋은 생각이 아니라고 말하는 것은 아니지만) 첫 번째 요소를 설정하고 나서 다음 작업을 수행했습니다.

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

(memcpy의 실장에 따라 달라지는) 더 이상 동작할 수 있을지 확신할 수 없지만, 초기 요소를 다음 요소에 반복적으로 복사함으로써 동작합니다.구조 어레이에서도 동작합니다.

방법 1:

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

정식 초기화 기법.

방법 2:.

int a[100] = {0};

하지만 주의할 필요가 있다

int a[10] = {1}; 

모든 값이 1로 초기화되지 않음

이 초기화 방법은 0 전용입니다.

그냥 하면

int a[100];

일부 컴파일러는 가비지 값을 취득하는 경향이 있기 때문에 항상 다음과 같이 하는 것이 좋습니다.

int a[1000] = {0};

클레멘스 실라프의 대답의 후속편입니다.이 버전에는 C++17이 필요합니다.

template <size_t Cnt, typename T>                                               
std::array<T, Cnt> make_array_of(const T& v)                                           
{                                                                               
    return []<size_t... Idx>(std::index_sequence<Idx...>, const auto& v)        
    {                                                                           
        auto identity = [](const auto& v, size_t) { return v; };                
        return std::array{identity(v, Idx)...};                                 
    }                                                                           
    (std::make_index_sequence<Cnt>{}, v);                                       
}

여기서 볼 수 있습니다.

언급URL : https://stackoverflow.com/questions/201101/how-to-initialize-all-members-of-an-array-to-the-same-value

반응형