구조체를 0 / null로 초기화 / 재설정


92
struct x {
    char a[10];
    char b[20];
    int i;
    char *c;
    char *d[10];
};

이 구조체를 채우고 값을 사용하고 있습니다. 다음 반복에서 모든 필드를 다시 사용 0하거나 null다시 사용하기 전에 재설정하려고 합니다.

어떻게 할 수 있습니까? 내가 사용 memset하거나 모든 멤버를 거쳐 개별적으로해야합니까?

답변:


109

초기 값으로 구조체의 const 정적 인스턴스를 정의한 다음 재설정 할 때마다이 값을 변수에 할당하면됩니다.

예를 들면 :

static const struct x EmptyStruct;

여기서는 초기 값을 설정하기 위해 정적 초기화 에 의존하고 있지만 다른 초기 값을 원한다면 구조체 이니셜 라이저를 사용할 수 있습니다.

그런 다음 루프를 돌 때마다 다음과 같이 작성할 수 있습니다.

myStructVariable = EmptyStruct;

1
@David Heffernan : memset모든 것을 재설정하려는 경우에만 사용 하는 것보다 낫습니까 0??
hari

9
@hari이 approch 나 자신을 선호합니다. 사용 memset하면 더럽게 느껴집니다. 가능한 한 컴파일러가 메모리 레이아웃에 대해 걱정하도록하는 것을 선호합니다. 엄밀히 말하면 이러한 사용은 memset이식이 불가능하지만 실제로 중요한 곳에서 코드를 컴파일 한 적이 있다면 놀라 울 것입니다. 따라서 원하는 경우 memset을 안전하게 사용할 수 있습니다.
David Heffernan

2
당신이 기본 초기화 값을 제공으로 @hari, 그것은 더 나은 개념이다 (객체 공장 패턴 같은 것을.)
디에고 세비야

1
@cnicutar 나는 이것을 알고있다. 내 대답은 memset을 사용하지 않는 것이 좋습니다. null 값을 할당하는 수단으로 memset을 사용하는 비 이식성을 지적한 부분에 대한 주석도 참고하십시오. 내 이전 의견은 0 비트가 항상 부동 소수점 0에 해당한다는 현실을 지적합니다.
David Heffernan 2011

1
@ kp11 인용하십시오
데이비드 헤퍼 넌

85

최신 C (C99)를 사용할 때 이러한 작업을 수행하는 방법은 복합 리터럴 을 사용하는 것 입니다.

a = (const struct x){ 0 };

이것은 David의 솔루션과 다소 유사하지만 빈 구조체를 선언하거나 선언할지 여부에 대해 걱정할 필요가 없습니다 static. const내가했던 것처럼를 사용하면 컴파일러는 적절한 경우 읽기 전용 저장소에 화합물 리터럴을 정적으로 할당 할 수 있습니다.


스택에 x 인스턴스를 생성하여 a에 복사합니까? 문제가 될 수있는 큰 구조물 / 작은 스택의 경우.
Étienne

1
모든 최적화와 마찬가지로 이것은 완전히 컴파일러에 따라 다르므로 컴파일러가 생성하는 내용을 확인해야합니다. "보통"현대 컴파일러에서는 그렇지 않습니다. 이것들은 초기화를 잘 추적 할 수 있으며 더 이상 필요하지 않은 작업 만 수행 할 수 있습니다. (그리고 그런 것들을 당신이 아주 천천히 아래를 측정하기 전에 문제가 있다고 생각하지 않습니다 그들은 일반적으로하지 않습니다..)
옌스 Gustedt

3
"이니셜 라이저 누락"경고는 실제로 가짜입니다. C 표준은 무슨 일이 일어나야하는지 정확히 규정 { 0 }하고 기본 이니셜 라이저로 간주합니다. 그 경고를 끄면 허위 경보입니다.
Jens Gustedt 2015

1
@JensGustedt이 타입 캐스팅이 정말로 필요합니까? 이렇게 쓸 수 없나요? struct xa = (const) {0};
패트릭

1
@Patrick, 구문은 비슷하지만 이것은 캐스트가 아니라 "복합 리터럴"입니다. 그리고 초기화와 할당을 혼합하고 있습니다.
Jens Gustedt

58

위의 모든 것보다 구조체 초기화에 표준 C 사양을 사용하는 것이 좋습니다.

struct StructType structVar = {0};

여기에 모든 비트가 0입니다.


13
나는 당신이 할 수 있다고 생각하지 않는 루프하지만 주위 때마다
데이비드 헤퍼 넌

2
이것은 실제로 작동한다고 가정합니다. 그러나 불행히도 gcc & g ++는 그것에 대해 불평합니다. gcc는 경고를 생성하고 g ++는 오류를 생성합니다. 나는 gcc와 g ++가 이것에 잘못이 있다는 것을 알고 있지만 (표준 C 사양을 따라야 함) 그럼에도 불구하고 좋은 이식성을 위해 이러한 제한을 고려해야합니다.
Cyan

3
@Cyan {}C ++에서 사용할 수 있습니다 . gcc 개발자는 C ++가 지원해야하는지 확신이 서지 않는{0} 것 같고 표준의 해당 부분에 익숙하지 않습니다.
마태 복음 읽기

@Matthew : 예, 실제로 {0}또는에 너무 많은 이식성 문제가 있었기 때문에 memset ()을 사용하게되었습니다 {}. C & C ++ 표준이 명확하고이 문제와 일치하는지 확실하지 않지만 컴파일러는 그렇지 않습니다.
시안

그런 경우에 이것이 작동할까요? struct StructType structVar = malloc (sizeof(StructType)); structVar ={0}
Sam Thomas

35

C에서는 다음을 struct사용하여 메모리를 제로화하는 것이 일반적인 관용구입니다 memset.

struct x myStruct;
memset(&myStruct, 0, sizeof(myStruct));

기술적으로 말하면 NULL기계 의 포인터가 정수 값 0으로 표시 된다고 가정하기 때문에 이식성이 있다고 생각하지 않지만 대부분의 기계에서 이것이 사실이기 때문에 널리 사용됩니다.

C에서 C ++로 이동하는 경우 모든 개체에이 기술을 사용하지 않도록주의하십시오. C ++는 멤버 함수 나 상속이없는 객체에서만 이것을 합법적으로 만듭니다.


2
C 표준에 따르면 NULL은 항상 0입니다. 미리 결정된 유효하지 않은 주소가 문자 그대로 0이 아니도록 시스템이 설계된 경우 해당 아키텍처의 컴파일러는 컴파일 중에 조정해야합니다.
Kevin M

9
@KevinM 예, "0"기호는 모두 0 인 경우에도 항상 NULL 포인터에 해당합니다. 그러나 memset을 사용하여 비트를 0으로 설정하면 컴파일러가 할 수있는 작업이 없습니다.
Adrian Ratnapala 2012

"C ++는 멤버 함수와 상속이없는 객체에서만 이것을 합법적으로 만듭니다." 유형이 '일반 오래된 데이터'로 간주되는지 여부입니다. 기준은 C ++ 언어 버전에 따라 다릅니다.
Max Barraclough

19

C99 호환 컴파일러가있는 경우 다음을 사용할 수 있습니다.

mystruct = (struct x){0};

그렇지 않으면 David Heffernan이 쓴대로해야합니다.

struct x empty = {0};

그리고 루프에서 :

mystruct = empty;

6

memset구조체의 크기와 함께 사용할 수 있습니다 .

struct x x_instance;
memset (&x_instance, 0, sizeof(x_instance));

1
나는 여기서 캐스트가 필요하다고 생각하지 않습니다. 맞나요?
templatetypedef

글쎄요, 저는 C ++에 너무 익숙해서 ... 글쎄요, C ++에서도 작동 할 것입니다.
Diego Sevilla

그래, 나는 충분히 구체적이지 않았다. cv 정규화 된 T에 대한 포인터는 cv 정규화 된 void *로 변환 될 수 있습니다. 모든 데이터 포인터, 함수 포인터는 완전히 다른 문제입니다. Kudos @Kevin
Marcus Borkenhagen

memset옵션이지만 사용할 때 기록 된 메모리가 세 번째 매개 변수와 정확히 동일한 크기인지 확인해야합니다. 따라서 유형의 크기가 아닌 실제 객체의 크기를 참조하는 것이 좋습니다. 현재 알고 있습니다 . IOW memset (&x_instance, 0, sizeof(x_instance));는 훨씬 더 나은 선택입니다. BTW : (void*)C ++에서도 캐스트가 불필요합니다.
늑대

(질문을 처리하지 못해서 미안합니다. 이제 더 좋습니다.)
Wolf

4

{}변수에 빈 집합 ( )을 할당 할 수 있다고 생각합니다 .

struct x instance;

for(i = 0; i < n; i++) {
    instance = {};
    /* Do Calculations */
}

이것은 유효한 C가 아니며 C99도 아닙니다. 위의 JensGustedt의 답변과 같은 복합 리터럴이어야합니다.
Anders

0
 struct x myX;
 ...
 memset(&x, 0, sizeof(myX));

5
나는 영업 이익은 memset 함수를 호출하는 방법을 알고 있다고 생각하지만, 오히려 문제는 현명한 여부 그렇게하지입니다
데이비드 헤퍼 넌

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