구조체 배열 끝에 빈 괄호 '{}'가 필요합니까?


59

Linux 커널에서 일부 코드 를 쳤습니다 .

static struct ctl_table ip_ct_sysctl_table[] = {
    {
        .procname   = "ip_conntrack_max",
        .maxlen     = sizeof(int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec,
    },
    // ...
    {
        .procname   = "ip_conntrack_log_invalid",
        .maxlen     = sizeof(unsigned int),
        .mode       = 0644,
        .proc_handler   = proc_dointvec_minmax,
        .extra1     = &log_invalid_proto_min,
        .extra2     = &log_invalid_proto_max,
    },
    { }
};

여기서 구조체 배열은로 끝납니다 { }. 어떤 목적으로 추가 되었습니까?
그건 그렇고,이 코드 위에 약간 의 구조체 배열이 있지만 끝에 빈 괄호가 없습니다.

구조체 배열 끝에 빈 괄호를 언제 사용해야합니까?


1
흠 0 배열의 끝을 문자열의 끝과 같은 신호로 추가하면 어떻게 될까요? 그냥 추측.
Eraklon

4
이것은 비표준 GCC 확장입니다. 그리고 문서가 거의 없거나 거의 없을 것입니다 ... 나는 모든 문서를 읽었고 빈 struct initializer 목록에 대해서는 아무것도 찾을 수 없습니다. 그러나 엄격한 ISO를 사용하지 않으면 컴파일됩니다 -pedantic.
Lundin

9
어쨌든, 이것은 배열의 끝을 표시하기 위해 모든 것이 0 / NULL로 설정된 항목 인 "sentinel"값입니다.
Lundin

Sentinels는 CPython 확장 모듈 에서도 일반적입니다 .
MaxPowers

답변:


38

이 특별한 변화는의 일부 sysctl을 그물 : 사용하지 않는 바이너리 sysctl을 코드를 제거 의 마지막 요소의 초기화 변화, 에릭 W. Biederman에 의해 커밋 ip_ct_sysctl_table에서 배열을 {0}하는 {}(그리고 수행하는 많은 다른 배열 초기화와 유사한 변경).

{0}패턴은 더 이상하지만 주변에 있었던 것으로 보이고, 모두 {0}또는 {}마지막 요소 초기화가 명시 적으로 언급 (리눅스 소스 코드에서) 일반적입니다 Terminating entry그들의 길이를 모른 채 이러한 배열을 소비 할 수있는 패턴의 존재는 가능성이 있으므로, 0으로 초기화 된 종료 항목을 칠 때 소비를 종료합니다. 예를 들어 sound/aoa/fabrics/snd-aoa-fabric-layout.c0으로 초기화하려는 의도의 유사한 배열에 대해서는 주석에 명시 적으로 언급됩니다.

static struct codec_connection toonie_connections[] = {
  {
      .connected = CC_SPEAKERS | CC_HEADPHONE,
      .codec_bit = 0,
  },
  {} /* terminate array by .connected == 0 */
};

11
기능면에서 100 % 동등한 GCC 확장에 찬성하여 표준 C를 삭제 한 이유를 아는 것이 흥미로울 것입니다. 표준 C 컴파일러에서 코드가 컴파일되는 것을 막는 것입니다. 즉, gcc 가이 기능을 문서화하지 않기 때문에 아마도 100 % 동등한 것입니다 ... 이것은 길이가 0 이 아닌 배열이며 빈 초기화 목록입니다.
Lundin

@Lundin int arr[] = {}(GNU 빈 이니셜 라이저 확장을 사용하고 있다면) 빈 배열이 되지 않을 것이다 ; 즉,의 크기 arr0?
dfri

1
@Lundin : 그러나 cppreference 페이지는 ISO / IEC 9899 : 2011의 문구와 충돌하여이를 허용합니다 (§6.7.9 (21)). 이니셜 라이저는 총계 멤버보다 의심 할 여지없이 "더 적다". 따라서 이것은 퀴어 컴파일러 확장이 아니라 합법적 인 C입니다.
Damon

2
@Damon 유효한 C가 아니며 잘 알려져 있습니다 ... gcc -pedantic-errors로 컴파일하십시오. 이유를 이해하려면 이니셜 라이저 목록의 실제 구문 인 6.7.9를 읽어야합니다. 이니셜 라이저가 하나 이상 있어야합니다. 여기에 설명 : stackoverflow.com/questions/17589533/...를 . 구체적으로 { initializer-list }다음 이니셜 라이저 목록 : designation(opt) initializer또는initializer-list , designation(opt) initializer
Lundin

2
@Lundin이 특정한 경우에는 전혀 모른다. 그러나 gcc 확장은 리눅스 커널에서 광범위하게 사용됩니다.
bobsburner

20

아마도 0으로 끝나는 문자열에 익숙 할 것입니다. ctl_table ip_ct_sysctl_table[]는 0으로 끝나는 배열입니다. 즉 마지막 배열 항목에는 모두 0의 멤버가 있습니다.


1
따라서 배열을 살펴보면 예를 들어 procnamenull이거나 maxlen0 일 때 끝에 도달했음을 알 수 있습니다 .
Paul Ogilvie

1
@PaulOgilvie : 글쎄, 예제는 불완전합니다. procnamechar[100]경우 ""null이 아닌입니다. 그러나 그렇지 않으면 그렇습니다.
MSalters

13

구조체 배열 끝에 빈 괄호 '{}'가 필요합니까?

C 구문 요구 사항을 충족시키기 위해 "구조 배열의 끝에 빈 괄호 '{}'"는 필요 하지 않습니다 .

구조체 배열 끝에 빈 괄호를 언제 사용해야합니까?

코드가 센티넬 값을 원할 때 .

프로그램이 모든 0의 최종 배열 요소를 갖는 것이 때로는 끝을 감지하는 데 유용 합니다. 필요가 배열의 응용 프로그램의 사용으로 제공 ctl_table ip_ct_sysctl_table[]하지 않는 C 언어의 필요성.


9

배열의 요소 수를 하나씩 늘리기 위해 배열 끝에서 0으로 초기화 된 요소입니다.

이 작은 데모를 고려하십시오.

#include <stdio.h>

struct Test
{
  int x;
  int y;
} arr[] =
{
    {1,2},
    {3,4},
//  {}
};

int main(void) {
    printf("%zu\n", sizeof(arr) / sizeof(arr[0]));
    return 0;
}

배열 초기화 목록 끝에서 arr주석을 제거하면 배열 의 크기 가 변경됩니다 {}.

출력 :

포함 // {}(배열에는 2 요소가 있음)

2

{}(배열은 3 원소를 가지고)

3

추가 설명 :

ip_ct_sysctl_table배열은 여기 한 곳에서 사용된다 :

in->ctl_table = kmemdup(ip_ct_sysctl_table,
                sizeof(ip_ct_sysctl_table),
                GFP_KERNEL);

여분 {}은 총 크기를 증가시킵니다 ip_ct_sysctl_table.


1
"어레이의 요소 수를 늘리기위한 것이 아니라"배열의 끝을 알리는 것입니다.
Paul Ogilvie

6
하하 싫어. 아이디어는 지금까지 아무도 확실하게 설명 할 수 없었습니다. 확실성의 가장 가까운 진술은 단순히 { }초기화 프로그램이라는 것입니다. 그러나 그 이유 는 여전히 불분명합니다. 따라서 어쨌든 아마도 그 단어 는 아마도 좋은 생각 일 입니다. :)
Ryyker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.