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


968

C에 큰 배열이 있습니다 ( 차이가있는 경우 C ++ 이 아님 ). 동일한 값의 모든 멤버를 초기화하고 싶습니다.

나는 이것을 한 번 간단한 방법으로 알고 있다고 맹세 할 수 있었다. memset()내 경우에는 사용할 수 있지만 C 구문에 내장 된이 작업을 수행 할 수있는 방법이 없습니까?


16
지금까지 C99 이상에서 가능한 지정된 초기화 표기법에 대한 답변은 없습니다. 예를 들면 다음 enum { HYDROGEN = 1, HELIUM = 2, CARBON = 6, NEON = 10, … };과 같습니다 struct element { char name[15]; char symbol[3]; } elements[] = { [NEON] = { "Neon", "Ne" }, [HELIUM] = { "Helium", "He" }, [HYDROGEN] = { "Hydrogen", "H" }, [CARBON] = { "Carbon", "C" }, … };. 생략 부호를 제거하면 해당 단편은 C99 또는 C11에서 컴파일됩니다.
Jonathan Leffler

실제로 abelenky의 답변은 지정된 이니셜 라이저를 사용하고 있지만 초기화 코드를 완전히 구성하지는 않았습니다.
Rob11311

memset ()이 도움이 될 수 있지만 값에 따라 다릅니다.
Nick

2
memset()특정 토론 : stackoverflow.com/questions/7202411/... 나는 단지 0 작동 생각
치로 틸리冠状病毒审查六四事件法轮功

답변:


1238

해당 값이 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으로 초기화되고 널값에 대한 포인터 등)


27
C ++ 표준을 통해 int array [10] = {}; 초기화하지 않습니다. 나는 이것이 유효한 C인지 확인하는 C 표준이 없다.
workmad3

54
6.7.8 C99 표준의 초기화 섹션을 보면 빈 이니셜 라이저 목록이 허용되는 것으로 보이지 않습니다.
Jonathan Leffler

7
C99에는 구조 및 배열 초기화를위한 많은 훌륭한 기능이 있습니다. 그것이 가지고 있지 않은 하나의 특징 (그러나 1966 년 포트란 IV)은 배열에 대한 특정 초기화를 반복하는 방법입니다.
Jonathan Leffler

8
@CetinSert : 작동하지 않는다는 것은 무엇을 의미합니까? 이 답변이해야 할 말을 정확하게 수행합니다. 코드의 주석에 표시된 내용은 수행하지 않지만 해당 주석은 잘못되었습니다.
Benjamin Lindley

9
@CetinSert : 당신은 그 의견에서 모든 요소가 -1로 설정되었다고 주장한 유일한 사람입니다. 이 답변은 올바르게 지정되지 않은 모든 요소가 0으로 설정되어 있다고 주장합니다. 코드의 결과는이 주장과 일치합니다.
Benjamin Lindley

394

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

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

자세한 설명을 확인하십시오 : http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Designated-Inits.html


12
이 구문은 컴파일 된 바이너리의 파일 크기를 크게 증가시킵니다. N = 65536 (1024 대신)의 경우 바이너리는 15KB에서 270KB로 점프합니다!
Cetin Sert

50
@CetinSert 컴파일러는 int정적 데이터 에 65536 s 를 추가해야합니다. 256K는 정확히 관찰 된 크기 증가입니다.
qrdl

15
@CetinSert 왜해야합니까? 지정된 초 기자에 국한되지 않는 표준 컴파일러 동작입니다. 당신이 정적 초기화 65536 개의 경우 int처럼의, int foo1 = 1, foo2 = 1, ..., foo65536 =1;같은 크기의 증가를 얻을 것이다.
qrdl

27
더 나은 방법 : "int array [] = {[0 ... 1023] = 5}", 배열의 크기는 자동으로 1024로 설정되어보다 쉽고 안전하게 수정할 수 있습니다.
Francois

4
@Francois 또는 2d 배열 bool array[][COLS] = { [0...ROWS-1][0...COLS-1] = true}의 경우 전체 형식보다 읽기 쉬운 지 확실하지 않습니다.
g33kz0r

178

여러 복사 붙여 넣기없이 동일한 값으로 큰 배열을 정적으로 초기화하려면 매크로를 사용할 수 있습니다.

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

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


12
나는 극단적 인 경우에만 이것을 고려할 것입니다. 확실히 memset이 그것을 표현하는보다 우아한 방법입니다.
u0b34a0f6ae

47
데이터가 ROM을 사용할 수 있어야하는 경우 memset을 사용할 수 없습니다.
Falken 교수 계약

9
전처리 기는 실제로 #defines에서 코드를 생성합니다. 배열 크기가 클수록 실행 가능 크기가 커집니다. 그러나 아이디어를 위해 확실히 +)
Leonid

7
@Alcott, 오래된 컴퓨터 및 여전히 많은 임베디드 시스템에서 코드는 결국 EPROM 또는 ROM에 배치됩니다 . ROM이 가능하다는 것은 임베디드 시스템에서 "플래시에 넣은 코드"를 의미하게되는데 이는 메모리가 런타임에 쓰여질 수 없다는 것과 거의 같은 의미를 갖기 때문입니다. 즉, 메모리를 업데이트하거나 변경하기위한 memset 또는 기타 명령을 사용할 수 없습니다. 그러나 상수는 프로그램이 시작되기 전에 표현되고 플래시되거나 ROM으로 표시 될 수 있습니다.
Falken 교수 계약

4
@ u0b34a0f6ae : VAL_1X단일 정수가 아닌 목록 인 경우에도이 방법을 사용할 수 있습니다 . 마이그레이션 가능한 상태와 마찬가지로, 이는 EEPROM 또는 플래시 메모리의 초기화 값을 정의하려는 임베디드 시스템에도 적용 할 수있는 방법입니다. 두 경우 모두를 사용할 수 없습니다 memset().
Martin Scharrer

63

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

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 myPoints[10][] = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9} };
Praveen Gowda IV

10
아니요. 가장 안쪽 치수를 생략하고 있습니다. 허용되지 않습니다. 컴파일러 오류가 발생합니다.
Frank Szczerba

4
C99에는 이니셜 라이저와 길이 추론이 모두 도입되었습니다.
Palec

3
@Palec : 아니오 — 사전 표준 C 시절 이후로 C에서 길이 유추가 발생했습니다 (K & R 1 판이 출판 된 이후로 아마도 그 이전에는 아마). 지정된 이니셜 라이저는 C99의 새로운 기능이지만 지정된 이니셜 라이저를 사용하지 않습니다.
Jonathan Leffler

53

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

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

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

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


8
이것은 C99 이니셜 라이저 구문이며 이미 다른 답변 중 일부에서 다룹니다. 당신은 유용하게 선언을 할 수도 있고 char const *array[] = { ... };심지어 char const * const array[] = { ... };할 수도 없습니까?
Jonathan Leffler

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

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


12
기록을 위해, 그것은 기본적으로 단지 느리고 더 장황한 버전입니다memset(myArray, VALUE, ARRAY_SIZE);
Benson

18
memset을 사용하여 int 배열을 255보다 큰 값으로 초기화하는 방법은 무엇입니까? memset은 배열의 크기가 바이트 인 경우에만 작동합니다.
Matt

21
@Benson : sizeof (int)> sizeof (char) 인 플랫폼에서는 위의 코드를 memset으로 바꿀 수 없습니다. 시도 해봐.
ChrisWue

13

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

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

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


memset배열을 초기화 하는 데 사용하는 예를 추가해 주 시겠습니까?
Sopalajo de Arrierez

8

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

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- 확장

지정된 inits

그런 다음 질문하십시오. C 확장은 언제 사용할 수 있습니까?

위의 코드 샘플은 임베디드 시스템에 있으며 다른 컴파일러의 빛을 절대 보지 못합니다.


6

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

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

5

배열이 int이거나 int 크기 또는 mem 패턴의 크기를 가진 것이 int에 정확한 시간에 맞는 경우 (예 : 모든 0 또는 0xA5A5A5A5) 가장 좋은 방법은 memset () 을 사용하는 것입니다 .

그렇지 않으면 인덱스를 이동시키는 루프에서 memcpy ()를 호출하십시오.


5

뺨에 약간의 혀 대답; 진술을 쓰십시오

array = initial_value

선호하는 배열 가능 언어 (광산은 포트란이지만 다른 많은 것이 있음)로 C 코드에 연결하십시오. 아마도 외부 기능이되도록 마무리하고 싶을 것입니다.


4

주어진 값으로 모든 유형의 배열을 초기화하는 빠른 방법이 있습니다. 큰 배열에서 잘 작동합니다. 알고리즘은 다음과 같습니다.

  • 배열의 첫 번째 요소를 초기화합니다 (일반적인 방법)
  • 설정되지 않은 부분으로 설정된 복사 부분, 다음 복사 작업마다 크기가 두 배로 증가

들면 1 000 000소자 int어레이는 일정한 루프 초기화 (I5, 2 개 코어, 2.3 GHz의 4GiB 메모리, 64 비트)보다 4 배 빠른 것이다 :

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

2
죄송하지만 사실이 아닙니다. 테스트하는 동안 컴파일 최적화를 켜는 것을 잊었을 수도 있습니다 (디버그 모드로 테스트 되었습니까?). 이것을 테스트하면 루프가 memfill보다 거의 항상 50 % 빠릅니다 (기계의 일부 부하 지터로 인해 '항상'). 그리고 memset (a, 0, sizeof (a)); 루프 필보다 두 배 빠릅니다.
RS1980

2
벤치마킹 코드와 마찬가지로 매우주의해야합니다. macOS Sierra 10.12.3이 설치된 MacBook Pro에서 실행되고 GCC 6.3.0을 사용하는 MacBook Pro에서 처음으로 루프는 약 4600 µs, memfill()코드는 약 1200 µs입니다. 그러나 이후 반복에서 루프는 약 900-1000 µs memfill()가 걸리고 코드는 1000-1300 µs가 걸립니다. 첫 번째 반복은 캐시를 채우는 시간에 영향을받을 수 있습니다. 테스트를 취소하고 memfill()처음으로 느립니다.
Jonathan Leffler

2

초기화 된 배열의 요소에 액세스하는 인덱스 순서를 언급 한 사람은 없습니다. 내 예제 코드는 이에 대한 예제를 제공합니다.

#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

4
<iostream>유효하지 않은 Cstd::cout, std::cin등은의 일부 std::namespaceC지원하지 않습니다 namespaces. 사용해보십시오 <stdio.h>위해 printf(...)대신.
Francis Cugler

2

모든 채터를 살펴보면 짧은 대답은 컴파일 타임에 최적화를 켜면 다음보다 나을 것입니다.

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

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


7
질문은 특별히 초기화를 요구했습니다. 이것은 명시 적으로 초기화가 아니라 초기화 후에 할당이 완료된 입니다. 즉시 수행 될 수 있지만 아직 초기화되지 않았습니다.
Andy

여러 번 호출되는 함수 내부의 대형 정적 조회 테이블에는 전혀 도움이되지 않습니다.
Martin Bonner는 Monica

... 원래 질문의 일부인 함수 내부의 정적 조회 테이블을 기억하지 마십시오. 단순하게 유지하십시오. @Community가 아마 그것을 못 박았을 것이라고 말했다.
JWDN

1
  1. 배열이 정적으로 선언되었거나 전역 인 경우 배열의 모든 요소에는 이미 기본 기본값 0이 있습니다.
  2. 일부 컴파일러는 디버그 모드에서 배열의 기본값을 0으로 설정합니다.
  3. 기본값을 0으로 설정하는 것은 쉽습니다. int array [10] = {0};
  4. 그러나 다른 값의 경우 memset () 또는 loop를 사용했습니다.

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


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

전체 배열의 크기가 될 때까지 o / p 5 5 5 5 5 5 ......


0

사용자 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()해당 유형을 지원 하도록 함수를 수정해야한다는 것 입니다.


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


0

초기화 지연 (예 : 클래스 멤버 생성자 초기화)의 경우 다음을 고려하십시오.

int a[4];

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

0

나는 원래 질문에 C ++이 아닌 C를 명시 적으로 언급하지만 당신이 (나 같은) C ++ 배열에 대한 솔루션을 찾고 있다면 여기에 깔끔한 트릭이 있습니다.

컴파일러에서 fold expressions를 지원하는 경우 template magic을 사용 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에서)


-1

질문에 요구 사항이 없으므로 솔루션은 일반적이어야합니다. 초기 멤버 값을 사용하여 지정되지 않은 가능한 구조 요소로 작성된 지정되지 않은 다차원 배열의 초기화 :

#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


1
이것이 솔루션인지 아닌지 의심됩니다. 나는 sizeof(void)심지어 유효한지 확실하지 않습니다.
Chris Lutz

3
작동하지 않습니다. 처음 두 개만 초기화되고 나머지는 모두 초기화되지 않습니다. Mac OS X 10.4에서 GCC 4.0을 사용하고 있습니다.
dreamlax

두 번째의 소스 데이터 memcpy()가 대상 공간과 겹치 므로 정의되지 않은 동작이 호출 됩니다. 순진한 구현으로 memcpy()작동 할 수도 있지만 시스템이 작동하도록 요구할 필요는 없습니다.
Jonathan Leffler

-1

그날로 돌아가서 (좋은 생각은 아닙니다) 첫 번째 요소를 설정 한 다음 :

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

그것이 더 이상 작동하지는 않지만 (memcpy의 구현에 달려 있음) 초기 요소를 다음에 반복적으로 복사하여 작동합니다-심지어 배열 배열에서도 작동합니다.


안정적으로 작동하지 않습니다. IMHO, 표준은 memcpy겹치는 경우에는 상향식 또는 하향식 복사 순서 와 같지만 지정된 기능을 제공해야 하지만 그렇지 않습니다.
슈퍼 캣

내가 말했듯이, 우리가 한 일은 안정적으로 작동하지 않았지만 그때 문서화되지 않은 기능을 피하는 것보다 효율성에 더 집중했습니다. 메모리를 앞으로 복사하는 것이 더 효율적이지만 사양에 따라 임의의 순서로 뒤로 복사하거나 여러 스레드로 나눌 수 없다고 말하는 것은 없습니다. memmove ()는 충돌없이 복사 할 수있는 기능을 제공합니다.
마이크

이것은 다른 답변 의 코드와 동일 하며 결함이 있습니다. 사용하면 memmove()작동하지 않습니다.
Jonathan Leffler

-2

병렬로 의미한다면, 표현식과 함께 사용될 때 쉼표 연산자가 그렇게 할 수 있다고 생각합니다.

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

또는 단일 구문을 의미하는 경우 for 루프에서 수행 할 수 있습니다.

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

// 인수 목록의 쉼표 연산자는 위에서 설명한 병렬 연산자가 아닙니다.

배열 편차를 초기화 할 수 있습니다.

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

malloc / calloc / sbrk / alloca / etc를 호출하여 객체에 고정 된 저장 영역을 할당 할 수 있습니다.

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

다음을 통해 멤버에 액세스하십시오.

*(array + index)

기타.


쉼표 연산자는 명목상 좌우 평가를 보장합니다. 표현식에 부작용이 없으면 연산을 병렬화 할 수 있지만 컴파일러가 그렇게하는 것은 드문 일입니다.
Jonathan Leffler
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.