컴파일러가 "missing initializer"라는 경고를 던지는 이유는 무엇입니까? 구조가 초기화되지 않았습니까?


79

프로그램을위한 일종의 프론트 엔드를 만들고 있습니다. 프로그램을 시작하기 위해 나는 CreateProcess()무엇보다도 STARTUPINFO구조에 대한 포인터를받는 호출을 사용하고 있습니다. 내가 사용했던 구조를 초기화하려면 :

이러한 경고 세트를 활성화하는 GCC로 프로그램을 컴파일 할 때 -Wall -Wextra첫 번째 줄을 가리키는 누락 된 초기화 프로그램이 있다는 경고가 표시됩니다.

그래서 결국 :

이런 식으로 컴파일러는 경고를하지 않습니다. 문제는 구조를 초기화하는 이러한 방법의 차이점은 무엇입니까? 첫 번째 방법을 사용하면 구조가 초기화되지 않습니까? 어느 것을 추천 하시겠습니까?


1
경고는 단지 경고입니다. 이 특정 경우에이 특정 경고를 무시해도됩니다. 컴파일러는 다음과 같은 경우에 도움이되는 경고를 내 struct struct_with_four_fields x = {1, 2, 3};보냅니다. 멤버 4 개 중 3 개만 초기화됩니다.
pmg

이전 댓글에서 4 번째 멤버는 0으로 초기화되었습니다.
pmg

5
이니셜 라이저 누락에 대한 경고는 일반적으로 불합리하지 않습니다. 4 개의 멤버가있는 구조가 있고 그중 3 개에만 이니셜 라이저를 제공하면 실수 일 가능성이 높습니다. 그러나 { 0 }모든 멤버를 0으로 초기화하기위한 일반적이고 잘 정의 된 관용구입니다 (각 하위 멤버에 대해 재귀 적으로 정의 됨). 따라서 gcc의 이후 버전이 특정 경우에 대해 경고하지 않도록 수정되었습니다.
Keith Thompson

@KeithThompson 무슨 소리 야? 저는 gcc 4.8.2 를 사용하고 있으며 질문이 5 년이 지난 후입니다. 추신 : 결국 링크하고 싶은 메일이 하나 더 있었지만 놀랍게도 누락되었습니다. 아마도 메일 서버는 모든 메시지를 저장하지 않을 것입니다. 슬프게도 메일은 문제를 다시 만나는 사람에게 유용합니다.
Hi-Angel

4
@ Hi-Angel : Solaris에서 gcc-4.8.1로 작은 프로그램을 컴파일하면 "경고 : 이니셜 라이저 누락"이 발생합니다. Linux Mint에서 gcc-4.8.2로 동일한 프로그램을 컴파일 할 때 경고가 표시되지 않습니다. 덧붙여, 링크obj = {0};메시지 의 행 은 유효한 C가 아니며 gcc 4.8.2는 구문 오류로이를 거부합니다. C ++로 컴파일하는 경우 다른 언어이고 gcc는 다른 프런트 엔드를 사용합니다. gcc의 C 컴파일러의 수정 사항은 g ++에 적용되거나 적용되지 않을 수 있습니다.
Keith Thompson

답변:


87

GCC는 지나치게 편집증적일뿐입니다. 제 생각에는 정당한 이유가 없습니다.하지만 GCC 관리자가 제가하는 C의 뉘앙스에 대해 더 많이 알고 있다는 것은 확실히 사실입니다.

GCC 메일 링리스트의 문제에 대한이 작은 토론 스레드를 참조하십시오.

결론은-구조체를 {0}초기화하면 실제로는 모든 것을 초기화합니다.

C99 표준은 6.7.8 / 21 "초기화-Sematics"에서 다음과 같이 말합니다.

중괄호로 묶인 목록의 이니셜 라이저가 집계의 요소 또는 멤버보다 적거나 알려진 크기의 배열을 초기화하는 데 사용되는 문자열 리터럴의 문자가 배열의 요소보다 적 으면 집계의 나머지는 다음과 같아야합니다. 정적 저장 기간이있는 객체와 동일하게 암시 적으로 초기화됩니다.

C90은 6.5.7에서 약간 다른 표현을 사용하여 본질적으로 동일하다고 말합니다 (즉, C99는 여기에 새로운 것을 추가하지 않았습니다).

또한 C ++에서는이 기능이 확장되어 빈 중괄호 " {}"가 개체에 대한 값 초기화를 수행합니다. 이는 멤버가 무엇인지 또는 유형이 몇 개의 멤버인지조차 알지 못하는 상황 (템플릿과 같은)이 있기 때문입니다. 이있을 수 있습니다. 따라서 좋은 습관 일뿐만 아니라 때때로 개체가 가질 수있는 멤버 수보다 짧은 이니셜 라이저 목록이 필요합니다.


19
나는 추가했다 -Wno-missing-field-initializers-Wno-missing-bracesGGC는 퍼팅 나에 대해 신음을 중지 그래서 = {0};내 구조를 위해. 이 경고를 비활성화하면 = {0};구조물 이외의 다른 것들에 대한 경고를 놓칠 수 있는지 아는 사람이 있습니까?
Matt Clarkson

4
수정 사항은 gcc 4.7.0 에 있지만 gcc 4.6.3 에는 없습니다 .
splicer

1
@splicer : 어떤 ""수정? 또한 mingw32-g++.exe (GCC) 4.7.2위의 관용구 (정확한 경우조차도) 에서이 경고를 컴파일 하고 받고 STARTUPINFO있습니다.
Jan Hudec 2013 년

2
@Jan Hudec : 개정판 172857 . 불행히도 이전 댓글의 URL이 더 이상 작동하지 않습니다. 수정과 관련된 버그는 다음과 같습니다. gcc.gnu.org/bugzilla/show_bug.cgi?id=36750
splicer

9
빈 중괄호 사용할 때 여전히도 GCC 4.9.3로 경고를 받고 있어요 {}또는 {0}내 C ++ 클래스의 초기화를 : /
카밀 Kisiel

21

구조를 다음과 같이 초기화하여 C ++ 프로그램의 GCC에 대해 쉽게 수정할 수 있습니다.

  • 며칠 전에 정확히 이렇게 했어요

1
이 답변의 가능한 함정은 C ++ 98에서 필드를 0으로 초기화하지 않았다는 것입니다. 제로 초기화 동작이 C ++ 03에 추가되었습니다.
MM

1
@MM 가능한 함정을 지적 해주셔서 감사하지만 2018 년 12 월에는 더 이상 위험한 상황이 아니어야한다고 생각합니다. BTW,이 답변이 가장 좋습니다!
Peter VARGA

@AlBundy 불행히도 C ++ 98 초기화를 사용하는 컴파일러가 아직 있습니다 (예 : 우연히 열어 본 C ++ Builder XE5 32 비트 모드)
MM

이 때문에 파일에 10 줄 이상의 코드를 추가해야했습니다. 정말 화가 났어요. 함수 호출에서 익명 개체를 전달하려고했습니다. {} 또는 {0}를 사용하면이 경고가 표시됩니다 (오류로 처리됨). 나는 () 사용하는 경우 GCC는 ... 그것은 함수 호출입니다 생각
bencemeszaros

15

를 사용하여 가능한 한 많은 경고를 요청했습니다 -Wall -Wextra.

이 경우 모든 필드를 지정하지 않았다는 경고가 표시됩니다. 이는 완벽하게 유효하지만 의도하지 않았을 수 있습니다.

다음을 추가하여이 경고를 억제 할 수 있습니다. -Wno-missing-field-initializers


12

이 웹 페이지는 근본적인 문제에 대해 자세히 설명합니다. http://ex-parrot.com/~chris/random/initialise.html

해결 방법으로 현재 해결 방법은이 경고를 선택적으로 억제하는 것입니다.

슬프게도 이것은 clang에서만 작동하며 GCC에서는 작동하지 않는 것 같습니다.


4
확인할 수 있습니다 : #pragma GCC diagnostic ignored "-Wmissing-field-initializers"GCC 컴파일러 4.2.1에서 수락했지만 아무것도하지 않습니다. gcc의 새 버전에 대한 확신이 없음
Maxim Kholyavkin 2014

1
@speakus, 나는 그것이 최신 (작성시) gcc (7.3.0)와 함께 작동하고 있음을 확인할 수 있습니다.
cydef

@cydef에 따르면 다른 의견과 내가 본 버그 보고서에 따르면 GCC는 더 이상 (GCC 5 기준) #pragma clang diagnostic ignored "-Wmissing-field-initializers". 이것이 사실인지 확인해야 할 것입니다.
WD40

1

C ++에서는 boost::initialized_value이 경고를 제거 하는 데 사용할 수 있습니다 . 에 대한 경고가 꺼져 있습니다 boost. 그래서 이것이 당신의 경우에 다른 경고를 유발하는지 모르겠습니다. 이렇게하면 경고를 비활성화 할 필요가 없습니다.

예:

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.