레이블을 사용한 C 구조체 초기화.작동하지만 어떻게?
-
05-07-2019 - |
문제
어제 루프를 발생시키는 구조체 초기화 코드를 발견했습니다.예는 다음과 같습니다.
typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
TEST_STRUCT test = {
second: 2,
first: 1
};
printf("test.first=%d test.second=%d\n", test.first, test.second);
}
놀랍게도 (나에게) 결과는 다음과 같습니다.
-> testFunc
test.first=1 test.second=2
보시다시피 구조체가 제대로 초기화되었습니다.나는 레이블이 붙은 진술이 그렇게 사용될 수 있다는 것을 몰랐습니다.나는 구조체 초기화를 수행하는 몇 가지 다른 방법을 보았지만 온라인 C FAQ에서는 이러한 종류의 구조체 초기화에 대한 예를 찾지 못했습니다.이것이 어떻게/왜 작동하는지 아는 사람이 있나요?
해결책
다음은 GCC 매뉴얼의 섹션입니다.이 섹션은 Structs 및 Array에 대한 지정된 이니셜 라이저의 구문을 설명합니다.
구조 이니셜 라이저에서 초기화 할 필드 이름을 지정하십시오..fieldName ='요소 값 앞에. 예를 들어 다음 구조가 주어지면
struct point { int x, y; };
다음 초기화
struct point p = { .y = yvalue, .x = xvalue };
동일합니다
struct point p = { xvalue, yvalue };
GCC 2.5 이후 쓸모없는 동일한 의미를 가진 또 다른 구문은 '입니다.'분야 명:', 여기에 표시된대로 :
struct point p = { y: yvalue, x: xvalue };
관련 페이지를 찾을 수 있습니다 여기.
컴파일러에 유사한 문서가 있어야합니다.
다른 팁
이들은 라벨이나 비트 필드가 아닙니다.
이것은 C99 전 며칠로 거슬러 올라가는 구조물 멤버를 초기화하는 구문입니다. 표준화되지 않았지만 EG GCC에서 사용할 수 있습니다.
typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };
C99에서, 특정 구조물 멤버를 초기화하기위한 구문은 표준으로 처음으로 도입되었지만 조금 다르게 보입니다.
typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };
예, 위에서 지적했듯이 이는 표준 C인 지정된 초기화 프로그램이지만 콜론 대신 마침표를 사용하도록 전환해야 합니다.그리고 당신이 지적한 바와 같이, 거기에 있는 대부분의 책은 여전히 구문이 1984년경 어딘가에 머물러 있고 이에 대해 언급하지 않습니다.더 재미있는 사실:
--지정된 초기화 프로그램을 사용하는 경우 지정되지 않은 모든 항목은 0으로 초기화됩니다.이는 다음과 같이 매우 큰 구조체에 도움이 됩니다.
typedef struct {
double a, b, c, d, e;
char label[100];
} too_many_type;
too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));
--또한 초기화되지 않은 줄에서 이 형식을 사용하기 위해 복합 리터럴 형식을 사용할 수 있습니다. 예:
too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};
이것들은 정말 훌륭한 기능이며 표준이라는 점에서 제가 생각할 수 있는 모든 C 컴파일러에서 지원됩니다.그들이 잘 알려지지 않은 것이 안타깝습니다.
실제로 "라벨링 된 진술"이 아니라 구조물의 이름의 이름의 필드에 초기 값을 제공하는 방법입니다.
GCC는 ": '"와 함께 지정된 이니셜 라이저의 쓸모없는 사용에 대한 경고를 제공하고 C99에서 대신 다음을 작성해야합니다.
TEST_STRUCT test = {
.second = 2,
.first = 1
};
해당 구문은 C 표준에 의해 정의되지 않습니다. 부분 6.7.8 Initialization
말한다
designation:
designator-list =
designator-list:
designator
designator-list designator
designator:
[ constant-expression ]
. identifier
컴파일러가 진단 메시지가없는 콜론으로 지정을 수락하는 경우 컴파일러가 표준을 준수하지 않거나 구성되지 않음을 의미합니다.