C의 비트 마스킹

Jinku Hu 2023년10월12일
  1. struct 키워드를 사용하여 C에서 비트 마스크 데이터 정의
  2. union과 결합 된struct를 사용하여 C에서 비트 마스크 데이터 정의
C의 비트 마스킹

이 기사에서는 C에서 비트 마스킹을 사용하는 방법에 대한 여러 방법을 보여줍니다.

struct 키워드를 사용하여 C에서 비트 마스크 데이터 정의

비트 마스크는 일반적으로 비트 필드 스타일 데이터 구조의 개별 섹션에 액세스하거나 설정하기위한 비트 연산에 사용됩니다. 반면에 비트 필드는 데이터를 효율적으로 저장하고 메모리 풋 프린트를 줄이는 데 사용됩니다. 또한 비트 연산은 일반적인 산술 연산보다 하드웨어에서 실행하는 것이 상대적으로 빠릅니다. 다음 예에서는struct 키워드를 사용하여 비트 필드의 구현을 보여줍니다.

이것은 기존의 멤버 액세스 연산자를 사용하여 주어진 비트 영역을 검색 할 수있는 객체를 생성하는 특수 표기법입니다. Bitfield 구조는 메모리에서 32 비트를 차지하는 단일unsigned 정수를 저장하지만, 그러나 23비트, 5비트, 4비트 값에서 각각 year, day, month 등 3개 섹션으로 접근이 가능하다. 결과적으로 Bitfield는 메모리에서 효율적으로 구현 된 날짜의 추상화를 나타냅니다.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

struct {
  uint32_t year : 23;
  uint32_t day : 5;
  uint32_t month : 4;
} typedef Bitfield;

int main() {
  Bitfield date = {2020, 13, 12};

  printf("sizeof Bitfield: %lu bytes\n", sizeof(date));
  printf("date: %d/%d/%d \n", date.day, date.month, date.year);

  return EXIT_SUCCESS;
}

출력:

sizeof Bitfield: 4 bytes
date: 13/12/2020

union과 결합 된struct를 사용하여 C에서 비트 마스크 데이터 정의

또는 전체 32 비트 숫자에 개별적으로 액세스 할 수 있도록 이전 구조에 union키워드를 추가 할 수 있습니다. 비트 필드 멤버에 액세스하는 것이 struct의 멤버에 액세스하는 것보다 느리기 때문에 비트 연산을 사용하여 별도의 ydm정수 멤버에 날짜 값을 할당합니다.

주어진 날짜를 나타내는 십진수는 논리적으로 서로 OR 처리되지만 그 전에는 daymonth값이 각각 23 자리와 28 자리 왼쪽으로 이동합니다. 후자의 숫자는 이러한 멤버가 비트 필드에서 차지하는 해당 비트 위치를 기반으로합니다. 출력을 인쇄해야 할 때 각 구성원은 여전히 별도로 액세스 할 수 있습니다.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

union {
  struct {
    uint32_t year : 23;
    uint32_t day : 5;
    uint32_t month : 4;
  };
  uint32_t ydm;
} typedef BitfieldFast;

int main() {
  BitfieldFast date_f;
  date_f.ydm = 2020 | (13 << 23) | (12 << 28);

  printf("sizeof BitfieldFast: %lu bytes\n", sizeof(date_f));
  printf("date_f: %d/%d/%d \n", date_f.day, date_f.month, date_f.year);

  return EXIT_SUCCESS;
}

출력:

sizeof BitfieldFast: 4 bytes
date_f: 13/12/2020

비트 마스크 사용의 또 다른 일반적인 예는 네트워킹의 IP 주소입니다. 즉, 주어진 주소가 속한 네트워크를 결정하는 네트워크 마스크와 함께 IP 주소가 제공됩니다. 네트워크 주소 계산은 IP 주소와 네트워크 마스크를 논리적으로 AND-ing하여 수행됩니다. 이 경우 IP 주소와 넷 마스크를 별도로 저장하도록 비트 필드struct를 정의했습니다. 논리적 AND-ing은 전체 32 비트 값에 대해 수행되지만 주소를 4 개의 8 비트 섹션으로 인쇄 할 때 멤버 액세스 연산자가 사용됩니다.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

union {
  struct {
    uint8_t first : 8;
    uint8_t second : 8;
    uint8_t third : 8;
    uint8_t fourth : 8;
  };
  uint32_t ip;
} typedef IPAddress;

int main() {
  IPAddress ip1 = {10, 127, 5, 1};
  IPAddress mask = {255, 255, 240, 0};
  printf("ip1: %d.%d.%d.%d\n", ip1.first, ip1.second, ip1.third, ip1.fourth);
  ip1.ip = ip1.ip & mask.ip;
  printf("net: %d.%d.%d.%d\n", ip1.first, ip1.second, ip1.third, ip1.fourth);

  return EXIT_SUCCESS;
}

출력:

ip1: 10.127.5.1
net: 10.127.0.0
작가: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook