brunch

매거진 Sinclair

You can make anything
by writing

C.S.Lewis

by Sinclair Aug 24. 2016

구조체, 공용체, 열거형

오 놀라워라~ C언어의 확장성 IV



구조체의 비트필드: 메모리를 잘게 쪼개서 사용 


구조체 멤버 중 비트 단위로 사용 가능한 멤버를 비트필드라고 합니다.

비트는 컴퓨터가 기억하는 요소의 최소 단위이지만 실제로 데이터를 처리하는 최소 단위는 8비트 묶음인 1바이트입니다.

그렇기 때문에 메모리가 아니어서 주소 값을 가질 수 없는 register 변수처럼 비트필드 멤버에 대하여 주소 값을 알려 주는 & 단항 연산자를 사용할 수 없게 됩니다.

이러한 비트필드는 비트 단위로 각각 의미를 갖게 되는 통신이나 하드웨어 제어에서 현재 가장 많이 사용하고 있습니다.

일반적으로 비트필드 멤버 타입으로 사용할 수 있는 것은 unsigned int 또는 signed int이지만 비트처리에서 부호는 거의 의미가 없기 때문에 unsigned int를 주로 사용합니다.

그리고 간혹 컴파일러에 따라서 (unsigned) long이나 (unsigned) short, (unsigned) char 타입을 지원하기도 하지만 이것은 표준이 아닙니다.

하지만 그 어떤 경우에도 정해진 타입의 비트 수를 넘어가는 사이즈를 가질 수 없습니다.


struct 구조체이름(태그) {

    멤버타입 멤버이름1: 비트수 ;

    멤버타입 멤버이름2: 비트수 ;

    멤버타입 멤버이름3: 비트수 ;

    멤버타입         : 비트수 ; // 지정 비트수 만큼 사용 안 함

    멤버타입 멤버이름4: 비트수 ;

     멤버타입         : 0 ; // 멤버타입 사이즈 내의 남은 모든 비트를 사용 안 함

    멤버타입 멤버이름n: 비트수 ;

    ...

} ;



만약에 아래의 비트 필드가 선언되었다면 실제 비트구조는 그림과 같습니다.


struct protocol {

    unsigned call:    3 ;

    unsigned check:   1 ;

    unsigned :        5 ; // 5비트만 사용 안 하고 비운다

    unsigned busy:    2 ;

    unsigned :        0 ; // 나머지 공간을 모두 사용 안 하고 비운다

    unsigned from:    8 ;

    unsigned to:      8 ;

    unsigned :        8 ; // 8비트만 사용 안 하고 비운다

    unsigned through: 8 ;

} ;



endian을 고려하지 않은 일반적인 비트들의 배치도(대부분 big-endian을 따른다.)


/***************************************************************

    struct protocol p = { .from = 124, .through = 126 } ;

    char * cp = (void*)& p ;

    for ( i = 0 ; i < 8 ; i ++ )

        printf("[%3d] " , ((char*)&p)[i]) ;

// [ 0] [ 0] [ 0] [ 0] [124] [ 0] [ 0] [126]

//     little-endian을 따르는 intel processor에서의 실행 결과

***************************************************************/  



    struct protocol p ;

    // 이렇게 값을 직접 줄 수도 있다.

    p.call = 7 ;

    p.check = 0 ;

    p.check = 2 ; // 범위를 넘어가는 값을 줘도 그 값의 마지막 비트로 설정된다

    p.busy = 3 ;

    p.from = 211 ;

    p.to = 123 ;

    p.through = 0 ;

    printf("%d %d %d %d %d %d\n",

         p.call, p.check, p.busy, p.from, p.to, p.through ) ;

    setProtocol(&p, something ) ;

    // 보통은 이런 식으로 함수를 통해 설정하는 것이 일반적  




이러한 비트필드와 다음에 나오게 될 공용체를 잘 알아두면 네트워크 프로그래밍의 프로토콜 설계를 이해하는데 매우 큰 도움이 될 것입니다. 비트필드는 메모리를 비트 단위로 쪼개서 사용하기 때문에 메모리를 낭비하지 않고 효율적으로 사용할 수는 있지만 멤버 연산자를 빈번히 사용해야 하는 등 일반 데이터 타입을 사용할 때 보다 처리 속도가 느려지는 문제점이 발생하기도 합니다.

過猶不及이고 Give and Take 입니다.

 
 









C언어 및 기타 프로그래밍 관련 질문은 오픈 카톡으로

group talk - https://is.gd/yourc

1:1 talk - https://is.gd/aboutc

#Sinclair #씽클레어 #싱클레어 #씽클레어도씨 #씨언어 #씨프로그래밍  #C언어 #Cprogramming #C_Programming #C #Programming #Clanguage #C_Language

매거진의 이전글 구조체, 공용체, 열거형
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari