2012-06-20 4 views
4

하드웨어의 레지스터에 해당하는 구조체가 있습니다.C에서 비트 필드에 액세스

typedef unsigned int uint32; 
typedef union A_u{ 
    uint32 words[4]; 
    struct { 

     uint32 a : 2; 
     uint32 b : 3; 
     uint32 unused : 27; 

     uint32 c : 2; 
     uint32 d : 3; 
     uint32 unused0 : 27; 

     uint32 unused1 : 1; 
     uint32 e : 1; 
     uint32 f : 1; 
     uint32 g : 1; 
     uint32 h : 1; 
     uint32 i : 1; 
     uint32 unused2 : 26; 

     uint32 reserved6 : 32; 
     }s; 
}A_t; 

main() 
{ 

    A_t obj; 
    uint32 val = 1; 

    memset(&obj, 0, sizeof(A_t)); 
    //fills data 
    read_data(&obj); 

    printf("0x%x\n", obj.words[2]); 
    printf("obj.s.h = %d\n", obj.s.h); 

} 

출력은

0x80000000에
obj.sh = 1

3 단어가 0x80000000에이지만, obj.sh 내가 할 수없는 오전 1로 표시됩니다 이것을 이해하다. 나는 powerpc에서 이것을 실행하고 있는데, 첫 번째 비트 필드는 최상위 비트이다.

+1

'printf ("sizeof (obj)는 % d 바이트입니다. \ n", sizeof (obj)); - Bitfield 패킹은 매우 컴파일러에 따라 다릅니다 – Roddy

+0

sizeof (obj)는 16입니다. 4 32 비트 워드 – user405369

+0

비트 필드가 서명되지 않았으므로 % d는 % u 여야합니다. 문제의 해결책이 아닐 수도 있습니다. – tinman

답변

4

컴파일러는 메모리 위치가 구조체 및 공용체의 멤버 및 기타 복잡한 데이터 구조와 어떻게 일치하는지에 관계없이 원하는만큼 자유롭게 수행 할 수 있습니다.

소스의 한 부분이 구조체를 보았고 다른 부분이 다른 방식으로 보았기 때문에 정렬 경계 문제로 인한 구조체를 사용하여 신비한 런타임 오류가 발생했습니다.

C는 기본적으로 구조체를 템플릿으로 사용하여 메모리 영역을 오버레이하고 다른 파일이 다른 방식으로 구조체를 보면 한 코드가 다른 구조체 멤버에 대한 주소 오프셋을 계산합니다.

일부 컴파일러에서는 구조체 멤버의 맞춤 경계를 지정할 수 있도록 팩 액션을 지정할 수있는 플러그인을 제공합니다.

하드웨어와의 호환성을 유지하기 위해 부호없는 문자 배열에 색인을 생성 한 다음 비트 연산자를 사용하여 8 비트 중 하나를 선택할 수 있기 때문에 가장 좋은 방법은 부호없는 문자 배열을 사용하는 것입니다. 그런 다음 다양한 액세스 함수, 클래스, 매크로 등에서 부호없는 문자 배열을 래핑하여 읽고 쓰고 자하는 실제 데이터를 조작 할 수 있습니다. 부호없는 문자 배열을 사용하면 이식성이 향상되는 경향이 있습니다.

비트 필드는 표시기와 플래그를 더 많은 메모리 절약 방식으로 유지 관리하는 방법이지만, 응용 프로그램 외부의 엔티티 (하드웨어 또는 소프트웨어)와의 통신에는 유용하지 않습니다. 그리고 컴파일러와 응용 프로그램이 실행되는 하드웨어에 따라 비트 필드를 사용하면 비트 필드에 액세스하고 패키지화하고 압축을 풀 때 작은 런타임 패널티가 생길 수 있습니다.