programing

memset() 또는 값을 초기화하여 구조체를 0으로 만들 수 있습니까?

sourcetip 2022. 8. 8. 23:11
반응형

memset() 또는 값을 초기화하여 구조체를 0으로 만들 수 있습니까?

으로 C Win32 API를 struct여러 필드가 있습니다.보통 이들 중 몇 개만 의미 있는 값을 가지며 다른 모든 값은 0으로 지정되어야 합니다.이는 다음 두 가지 방법 중 하나로 수행할 수 있습니다.

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

또는

STRUCT theStruct = {};

두 번째 변형 모델은 외관이 깔끔해 보입니다. 원라이너로, 잘못 입력되어 오류가 발생할 수 있는 매개 변수가 없습니다.

첫 번째 변종과 비교했을 때 어떤 단점이 있나요?어떤 변종을 사용해야 하며 그 이유는 무엇입니까?

그 두 가지는 그 의미에 있어서 매우 다르다.첫 번째 것은memset이 함수는 메모리의 버퍼를 특정 값으로 설정하는 것을 목적으로 합니다.개체를 초기화하는 두 번째 항목입니다.코드로 설명하겠습니다.

POD 타입의 멤버만을 가지는 구조를 상정합니다.('일반적인 오래된 데이터' - C++의 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 = {} ★★★★★★★★★★★★★★★★★」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오브젝트가 어디에 있는지 메모리를 설정합니다.b0으로 하다객체는 되고 그 인 TestStruct 객체의 가 되면 TestStruct 객체는 파기됩니다.std::string b을 볼.memset.

그래서, 현실은 그런 것들이 매우 다르다는 것입니다. 그리고 가끔 당신이 해야 할 필요가 있지만.memset어떤 경우에는 전체 구조가 0이 되도록 하는 것이 항상 중요하며, 두 번째 예시와 같이 실수를 하지 않도록 하는 것이 중요합니다.

의 투표 - 의의투 - 의의 my my my my my를 사용하다memset필요한 경우에만 개체에서 기본 초기화를 사용합니다.x = {}른른른른

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

또한 일부 API에서는 구조가 실제로 all-bits-zero로 설정되어야 합니다.예를 들어 Berkeley 소켓 API는 구조체를 다형식으로 사용하므로 명확한 값뿐만 아니라 구조 전체를 0으로 설정하는 것이 중요합니다.API 문서에는 구조가 정말 all-bits-zero여야 하는지 여부가 기재되어 있어야 합니다만, 부족한 경우가 있습니다.

하지만 이 두 가지 또는 유사한 경우가 모두 해당되지 않는 경우, 그것은 당신에게 달려 있습니다.나는 구조를 정의할 때 가치 초기화를 선호한다. 왜냐하면 그것이 더 명확한 의도를 전달하기 때문이다.가 있는 는, 「Zeroize」를 참조해 주세요.memset유일한 선택입니다(각 멤버를 수동으로 0으로 초기화하는 것 이외에는, 일반적으로는 그렇지 않습니다만, 특히 큰 구조에서는 그렇습니다).

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

int a;
char b;
int c;

그 후 "b"와 "c" 사이에 패딩 바이트가 삽입됩니다.memset()는 0으로 하고, 반대로는 0으로 하지 않기 때문에 3바이트의 가비지가 발생합니다(ints가 32비트인 경우).구조를 사용하여 파일을 읽고 쓰려는 경우 이 기능이 중요할 수 있습니다.

말씀하신 것처럼 깨끗하고 오류가 적기 때문에 값 초기화를 사용하겠습니다.나는 그것을 하는 데 아무런 단점도 없다고 본다.

.memset0으로 하다

컴파일러의 경우STRUCT theStruct = {}; 되면 '아까운명하다.memset( &theStruct, 0, sizeof( STRUCT ) );실행 파일에 있습니다.일부 C 함수는 런타임 설정을 수행하기 위해 이미 링크되어 있기 때문에 컴파일러는 memset/memcpy와 같은 라이브러리 함수를 사용할 수 있습니다.

컴파일 시에 실행할 수 있기 때문에 값이 초기화됩니다.
또한 올바르게 0으로 모든 POD 유형을 초기화합니다.

은 runtimememset()에됩니다.
또한 구조가 POD가 아닌 경우에도 memset()을 사용하는 것이 의심됩니다.
int 이외의 타입은 올바르게 초기화되지 않습니다(제로).

흔하지는 않지만 두 번째 방법은 플로트를 0으로 초기화하는 장점이 있는 것 같습니다.memset을 하는 동안에도

포인터 멤버가 많고 향후 추가될 예정인 경우 memset을 사용하는 데 도움이 될 수 있습니다. ★★★★★★★★★★★★와의 조합assert(struct->member)콜의 초기화를 잊은 부정한 포인터를 특정하려고 하는 랜덤크래시를 회피할 수 있습니다.하지만 저처럼 건망증이 심하지 않다면 회원 초기화가 가장 좋을 거예요!

, 구조를 퍼블릭 API의 일부로 사용하는 경우에는 클라이언트 코드를 취득하여 memset을 요건으로 사용해야 합니다.이는 새로운 멤버를 추가할 수 있고 클라이언트코드에 의해 (위험할 가능성이 있는) 미초기화 스테이트가 아닌 memset 콜에서 자동으로 NULL이 되기 때문에 향후 증명에 도움이 됩니다.예를 들어 소켓 구조를 사용할 때 다음과 같이 합니다.

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

반응형