[c] 배열의 모든 멤버를 동일한 값으로 초기화하는 방법은 무엇입니까?

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++

이니셜 라이저가 지정되지 않은 경우 정적 저장 기간을 가진 객체는 0으로 초기화됩니다.

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

그리고 “0”이 반드시 “all-bits-zero”를 의미하는 것은 아니므로, 위를 사용하는 것이 memset ()보다 더 우수하고 이식성이 뛰어납니다. (부동 소수점 값은 +0으로 초기화되고 널값에 대한 포인터 등)


답변

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

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

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

편집 : 가능한 유용한 확장

( Jonathan Leffler 제공 )

다음과 같이 쉽게 일반화 할 수 있습니다.

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

매크로 이름은 협상 가능합니다.


답변

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

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

아니다.


답변

이 구문을 사용하는 코드를 보았습니다.

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

특히 유용한 것은 열거 형을 인덱스로 사용하는 배열을 만드는 경우입니다.

enum
{
    ERR_OK,
    ERR_FAIL,
    ERR_MEMORY
};

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

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

열거 형 값 중 일부를 순서대로 작성하지 않아도 상황이 순서대로 유지됩니다.

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


답변

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

배열의 크기가 변경되는 경우


답변

위에서 설명한 것처럼 전체 정적 이니셜 라이저를 수행 할 수는 있지만 배열 크기가 변경되면 배열이 커질 때 적절한 초기화 프로그램을 추가하지 않으면 쓰레기가 생길 수 있습니다.

memset은 작업 수행에 대한 런타임 적중을 제공하지만 코드 크기 적중은 배열 크기 변경에 영향을받지 않습니다. 배열이 수십 개의 요소보다 클 때 거의 모든 경우 에이 솔루션을 사용합니다.

배열을 정적으로 선언하는 것이 정말로 중요하다면 프로그램을 작성하여 빌드 프로세스의 일부로 만드는 프로그램을 작성했습니다.