program story

memset () 또는 구조체를 0으로 초기화하는 값 초기화?

inputbox 2020. 11. 30. 08:08
반응형

memset () 또는 구조체를 0으로 초기화하는 값 초기화?


Win32 API 프로그래밍에서는 struct여러 필드에 C를 사용하는 것이 일반적 입니다. 일반적으로 그중 몇 개만 의미있는 값을 가지며 나머지는 모두 0으로 설정해야합니다. 이는 다음 두 가지 방법 중 하나로 달성 할 수 있습니다.

STRUCT theStruct;
memset( &theStruct, 0, sizeof( STRUCT ) );

또는

STRUCT theStruct = {};

두 번째 변형은 더 깔끔해 보입니다. 한 줄로되어 있으며, 잘못 입력 할 수있는 매개 변수가 없어 오류가 심해질 수 있습니다.

첫 번째 변형에 비해 단점이 있습니까? 어떤 변형을 사용해야하며 그 이유는 무엇입니까?


이 두 구조는 그 의미 매우 다릅니다. 첫 번째 는 메모리 버퍼를 특정 값memset 으로 설정 하는 함수를 사용 합니다 . 두 번째 는 객체초기화합니다 . 약간의 코드로 설명하겠습니다.

POD 유형의 구성원 있는 구조가 있다고 가정합니다.

struct POD_OnlyStruct
{
    int a;
    char b;
};

POD_OnlyStruct t = {};  // OK

POD_OnlyStruct t;
memset(&t, 0, sizeof t);  // OK as well

이 경우에 POD_OnlyStruct t = {}or를 쓰는 것은 POD_OnlyStruct t; memset(&t, 0, sizeof t)큰 차이를 만들지 않습니다. 여기서 우리가 가진 유일한 차이점 사용되는 경우 0 값으로 설정되는 정렬 바이트 memset입니다. 일반적으로 해당 바이트에 액세스 할 수 없기 때문에 차이가 없습니다.

반면에 질문에 C ++로 태그를 지정 했으므로 POD 와 다른 멤버 유형을 사용 하여 다른 예제를 시도해 보겠습니다 .

struct TestStruct
{
    int a;
    std::string b;
};

TestStruct t = {};  // OK

{
    TestStruct t1;
    memset(&t1, 0, sizeof t1);  // ruins member 'b' of our struct
}  // Application crashes here

이 경우 다음과 같은 표현식을 사용하는 TestStruct t = {}것이 좋으며를 사용하면 memset충돌이 발생합니다. 사용하면 다음과 같은 일이 발생합니다. memset유형의 객체 TestStruct가 생성되어 std::string구조의 구성원이기 때문에 유형의 객체가 생성 됩니다. 다음으로 memset객체 b가 위치한 메모리 를 특정 값 (예 : 0)으로 설정합니다. 이제 TestStruct 객체가 범위를 벗어나면 파괴 될 것이며 std::string b해당 객체의 모든 내부 구조가 memset.

따라서 현실은 이러한 것들이 매우 다르며 , 경우에 memset따라 전체 구조를 0으로 설정 해야하는 경우도 있지만 , 수행중인 작업을 이해하고 두 번째 에서처럼 실수하지 않도록하는 것이 항상 중요합니다. 예.

내 투표- 필요한 경우 에만memset 개체에 사용하고 다른 모든 경우에는 기본 초기화 사용합니다 .x = {}


구조 멤버에 따라 두 변형이 반드시 동일하지는 않습니다. memset값 초기화는 모든 멤버를 값 0으로 초기화하는 반면 구조를 all-bits-zero로 설정합니다. C 표준은 부동 소수점 값이나 포인터가 아닌 정수 유형에 대해서만 동일하도록 보장합니다.

또한 일부 API는 구조가 실제로 all-bits-zero로 설정되어야합니다. 예를 들어, Berkeley 소켓 API는 구조를 다형 적으로 사용하며, 여기서 명백한 값뿐만 아니라 전체 구조를 0으로 설정하는 것이 중요합니다. API 문서에는 구조가 실제로 모두 0 비트 여야하는지 여부가 표시되어야하지만 부족할 수 있습니다.

그러나 이들 중 어느 것도 적용되지 않거나 유사한 사례가 적용되지 않는다면 그것은 당신에게 달려 있습니다. 구조를 정의 할 때 의도를 더 명확하게 전달하기 때문에 값 초기화를 선호합니다. 물론 기존 구조를 제로화해야하는 경우 memset유일한 선택입니다 (각 멤버를 수동 으로 제로화하는 것과는 별개로, 특히 대형 구조의 경우 일반적으로 수행되지 않음).


구조체에 다음과 같은 것이 포함되어있는 경우 :

int a;
char b;
int c;

Then bytes of padding will be inserted between "b" and "c". memset() will zero those, the other way will not, so there will be 3 bytes of garbage (if your ints are 32 bits). If you intend to use your struct to read/write from a file, this might be important.


I would use value initialization because it looks clean and less error prone as you mentioned. I don't see any drawback in doing it.

You might rely on memset to zero out the struct after it has been used though.


not that it's common, but I guess the second way also has the benefit of initializing floats to zero. While doing a memset would certainly not


In some compilers STRUCT theStruct = {}; would translate to memset( &theStruct, 0, sizeof( STRUCT ) ); in the executable. Some C functions are already linked in to do runtime setup so the compiler have these library functions like memset/memcpy available to use.


The value initialization because it can be done at compile time.
Also it correctly 0 initializes all POD types.

The memset() is done at runtime.
Also using memset() is suspect if the struct is not POD.
Does not correctly initialize (to zero) non int types.


If there are lots of pointer members and you are likely to add more in the future, it can help to use memset. Combined with appropriate assert(struct->member) calls you can avoid random crashes from trying to deference a bad pointer that you forgot to initialize. But if you're not as forgetful as me, then member-initialization is probably the best!

However, if your struct is being used as part of a public API, you should get client code to use memset as a requirement. This helps with future proofing, because you can add new members and the client code will automatically NULL them out in the memset call, rather than leaving them in a (possibly dangerous) uninitialized state. This is what you do when working with socket structures for example.

참고URL : https://stackoverflow.com/questions/1998752/memset-or-value-initialization-to-zero-out-a-struct

반응형