2014-01-18 5 views
4

다음 작업을 시도하고 있지만 NSValue의 생성 방법은 nil을 반환합니다. 구조체의 C 비트 필드가 지원되지 않습니까?비트 필드가있는 C 구조체에서 NSValue를 만들 수 있습니까?

struct MyThingType { 
    BOOL isActive:1; 
    uint count:7; 
} myThing = { 
    .isActive = YES, 
    .count = 3, 
}; 

NSValue *value = [NSValue valueWithBytes:&myThing objCType:@encode(struct MyThingType)]; 
// value is nil here 
+0

비트 필드 지정자를 제거하면 작동합니까? –

+0

재미있는 질문이지만, 비트 필드를 전혀 사용하지 말 것을 권합니다. –

+3

어쨌든 NSValue에 넣는 오버 헤드를 추가 할 때 비트 필드를 사용하면 어떨까요? –

답변

6

무엇보다도 인기를 끌려는 그의 의견에 아주 좋은 지적한다 : 왜 (주로 당신이 그들을 필요로 패딩 비트를 추가 수동으로 마이크로 최적화 않거나 중 하나에 사용되는) 비트 필드 지정자를 사용하여 귀찮게을, 으로 변경 한 다음을 모두 NSValue의 인스턴스로 마무리하십시오.
그것은 카펫을 도자기하지 않도록 부엌에 살고있는 후 성을 구입하지만처럼 ...

나는 생각하지 않는다 그것은 ... 사과 DEV-문서 came up with this을 통해 빠른 구보를가한다 실제로 비트 필드와 관련하여 고려해야 할 몇 가지 문제가 있습니다.

은 또한 단지 비트 필드 + NSValue 정말 함께 잘 재생되지 않는 이유 을 설명하는 this을 발견했습니다.
특히 구조체가 NSValue의 데이터를 읽는 데 ...
구조체가 8 비트로 패딩되어 있습니다. 이제이 비트들은 2 int 또는 1 long 또는 뭔가로 읽을 수 있습니다 ... 내가 링크 된 페이지에서 읽은 것으로부터, 이것이 일어나는 일은 거의 일어나지 않습니다.
기본적으로 비트 필드를 사용하는 경우 NSValue은 실제 유형을 결정할 수 없습니다. 모호한 경우에는 int (대부분의 경우 너비 4)가 가정되고 언더 플로우/오버플로가 발생하고 손이 엉망입니다.

컴파일러는 여전히 가지고 있기 때문에 당신이 '원 좋은 기회가 있기 때문에 어떤 멤버 실제로 저장되어있는, 꽤, 일 (을)의 캐릭터 라인 형식 정의 정렬을 전달하는 데 충분하지 않는 경우에 일부 자유 컴파일러 최적화 등으로 인해 실제 구조체 자체를 이해할 수 있어야합니다.

구조체 을 지원해야하기 때문에 비트 필드 지정자를 삭제하는 것이 좋습니다 ... 적어도, 내가 시도한 마지막 시간, 간단한 기본 형식 struct 잘 작동했습니다.

+0

'@encode'를 읽는 모든 코드가'@encode'가 설명 ​​할 수있는 모든 타입을 처리 할 수있는 것은 아닙니다. 모든 타입이'@encode'에 의해 정확하게 기술 될 수있는 것은 아닙니다. –

+1

NSValue 대신 NSData를 사용하여이 구조체를 래핑 할 수 있습니다. –

0

노조로 해결할 수 있습니다. NSValue으로 지원되는 유형의 다른 멤버가 있고 구조보다 큰 크기의 유니온에 구조체를 넣기 만하면됩니다. 귀하의 경우에 이것은 long에 대해 분명합니다.

union _bitfield_word_union 
{ 
    yourstructuretype bitfield; 
    long plain; 
}; 

컴파일 타임에 크기가 계산되는 배열을 사용하여 구조의 크기를 조정하는 것에 대해 더 강력하게 만들 수 있습니다. (sizeof()도 컴파일 시간 연산자는 것을 기억하시기 바랍니다.)

char plain[(sizeof(yourstructuretype)/sizeof(char)]; 

그런 다음 당신이 노동 조합에 비트 필드와 구조를 저장하고 plain 회원을 읽을 수 있습니다.

union converter = { .bitfield = yourstructuretypevalue }; 
long plain = converter.plain; 

NSValue 인스턴스 생성시이 값을 사용하십시오. 독서는 반대 방향으로해야합니다.

나는 다른 멤버 값 (plain)을 통해 멤버의 값 (bitfield)을 읽고 그것을 다시 저장한다는 것을 기대할 수 있기 때문에 C99의 기술적 교정을 통해 표준 준수 (타입 펀칭이라고도 함)되었다고 확신한다. 읽히는 구성원이 최소한 작성된 구성원만큼 큰 경우 정의됩니다. (plain에는 정의되지 않은 비트 9-31/63이있을 수 있지만 그것에 대해 신경 쓸 필요는 없습니다.) 그러나 실제와 일치합니다.

더티 해킹? 아마도. C99라고 부를 수도 있습니다. 그러나 비트 필드를 NSValue과 함께 사용하면 더러운 해킹을 사용하는 것처럼 들립니다.