2009-07-22 5 views

답변

2

C# 명시 적 구조체는 참조/포인터 크기의 멤버와 관련하여 몇 가지 문제가 있습니다.

명시 적으로 위치를 지정해야하지만 "sizeof (IntPtr)"는 컴파일 타임 상수가 아니기 때문에 (C++ sizeof와 달리) 어셈블리를 사용할 수있을 때 명시 적 구조체에 포인터 크기 멤버를 사용할 수 없습니다 32 비트 및 64 비트 프로세스에서

또한, 참조와 포인터 사이에 "변환"명시 적 구조체를 사용할 수있다 :이 작업을 수행 할 때

[StructLayout(LayoutKind.Explicit)] 
struct Test 
{ 
    [FieldOffset(0)] 
    public IntPtr ptr; 
    [FieldOffset(0)] 
    public string str; 
} 

, 어셈블리가 안전하지 않은 코드 권한이 필요합니다; GC가 구조체 내용으로 무엇을해야하는지 알지 못한다는 문제가 있습니다 - GC가 추적해야하는 포인터입니까 아니면 정수입니까?

귀하의 질문에 대답 : "당신이 할 수있는 C++ 노조로 할 수있는 일이 있나요?

예, 포인터의 하위 비트에 2 비트의 데이터를 집어 넣는 것이 C++에서 유용 할 때가 있습니다. 이는 포인터가 정렬 될 때 포인터의 두 최하위 비트가 항상 0이기 때문에 가능합니다.

지저귐, 2 비트 정수의 이중 연결 목록을 작성하는 경우 포인터와 데이터를 모두 32 비트로 저장할 수도 있습니다. ("prev^next^data", XOR linked list 참조)

그러나 GC를 혼동하는 것처럼 C#에서는 이와 같은 작업을 수행 할 수 없습니다.

+0

마샬링은 일단 네이티브 데이터가되면 레이아웃과 관련이 있습니다. IntPtr은 여전히 ​​C# 형식입니다. 데이터 영역에 마샬링되기 전까지는 관리되는 플랫폼 아래에 구성원으로 존재합니다. –

1

아니요. LayoutKind 속성은 interop에서 데이터를 C++ 유니온으로 마샬링하는 방법입니다. 구조체를 사용하여 C#의 레이아웃을 완벽하게 제어 할 수 있으므로 C++의 union 키워드보다 훨씬 유연합니다.

+0

-1 이것은 완전히 잘못되었습니다. 명시 적 (Explicit)은 정확한 오프셋을 제어 할 수있는 유연성을 제공합니다. 유니언 지원은 주요 관심사가 아니었고 중복 배열 및 기타 비 배열 유형과 같은 많은 것들이 전혀 작동하지 않습니다. –

0

데이터 위에 다른 유형의 배열을 겹칠 수 없습니다. 예를 들어, byte [4]와 int16, int16을 오버레이 할 수 없습니다. 런타임에 충돌이 발생합니다.