2017-12-24 3 views
4

이 코드를 고려하십시오. 패딩의 존재가 보장됩니다. 그 static_assert의와구조체 또는 공용체의 패딩에 액세스하는 것이 안전합니까?

static_assert(_Alignof(char) < _Alignof(double), "Flip!"); 
static_assert(sizeof(char) < sizeof(double), "Flop!"); 

struct S { 
    char c[1]; 
    double d; 
}; 
union U { 
    char c[1]; 
    double d; 
}; 

static_assert(sizeof(struct S) == _Alignof(double) * sizeof(double), "Fudge!"); 
static_assert(sizeof(union U) == sizeof(double), "Futz!"); 

S s; U u; 
s.c[1] = 0; // What? 
u.c[1] = 0; // What? 

, 그것은 패딩 중간이나 끝이 확실합니다. 그것들에 접근하는 것이 안전합니까?

+5

Afaik 컴파일러는 가능할 때마다 디버그 빌드의 배열에 대한 바운드 검사를 수행 할 수 있으므로 UB입니다. punnig 유형에 관해서는 그것에 대한 질문이 있습니다 : [C99에서 un-type union을 통한 유형 - 펀닝이 C11에서 지정 되었습니까? Ask] (https://stackoverflow.com/questions/11639947/is-type-punning-through-a-union-unspecified-in-c99-and-has-it-become-specified) – Ivan

+1

alligbnment는 그리 많지 않습니다. 이웃 필드 때문에 대개 감지되지 않는 배열 오버로드에 이르지 만'c [1]'은 오류입니다 –

+3

패딩에 안정적으로 액세스 할 수 없습니다. 구조체 (유니언) 할당에서 복사중인 패딩에 의존 할 수 없습니다. 거기에 바이트가 있다는 의미에서 액세스하는 것은 "안전"합니다. 의미 있고 신뢰할 수있는 것은 없습니다. 만약 당신이 그런 바이트들을 사용한다면, 명시 적으로 :'struct S2 {char c [1]; 짧은 s; int i; 더블 d; }'(32 비트 Intel x86을 제외한 대부분의 시스템에서는 질문에서'struct S'와 크기가 같습니다). 그리고 첫 번째 정적 어설 션은 32 비트 x86에서 시작됩니다. –

답변

0

패딩 비트를 포함하더라도 memcpy(), memset() 또는 이와 유사한 구조체 전체가 안전합니다. 그러나 패딩이 그 값을 유지한다는 가정은 할 수 없습니다.

따라서 패딩 비트에 액세스하는 유일한 용도는 코드를 작성하여 일부 상황에서 액세스하지 못하도록하는 것입니다.

memcmp()과 같은 작업의 경우 결과가 예측할 수 없으므로 패딩 비트에 액세스하는 것은 여전히 ​​잘못된 것입니다.

관련 문제