본문 바로가기
개발일지/Computer Science

비트맵, 문자열, 복합 데이터 타입

2022. 2. 3.

비트맵

비트맵 이란 디지털 이미지를 저장하는 데 쓰이는 이미지 파일 포맷 또는 저장 방식의 한 형태이다.

기본 데이터 타입을 사용해 배열을 만들면

기본 데이터가 너무 클 때도 있는데 이때 비트맵을 사용한다.

 

예를들어 35비트를 추적하고 싶다고하자

아래 그림처럼 8비트 5개가 있으면 35비트를 충분히 담을 수 있다.

7 6 5 4 3 2 1 0
15 14 13 12 11 10 9 8
23 22 21 20 19 18 17 16
31 30 29 28 27 26 25 24
          34 33 32

 

비트맵에 대해 수행할 수 있는 기본 연산은

- 비트 설정하기 (1로 설정하기) 

- 비트 지우기(0으로 만들기)

- 비트가 1인지 검사하기

- 비트가 0인지 검사하기

이렇게 네가지이다

 

특정 비트가 있는 바이트 찾기

정수 나눗셈을 통해 특정 비트가 들어 있는 바이트를 찾을 수 있다.

필요한 연산은 8로 나누고

다음 단계로 비트 위치에 대한 마스크를 만들어야 한다.

비트 번호와 0x07을 AND 해서 하위 3비트를 얻고,

그 후 앞에서 얻은 값을 왼쪽으로 시프트 하면 마스크를 얻는다.

 

자원이 사용가능하거나 사용중인지 여부를 나타낼 때도 비트맵을 유용하게 사용할 수 있다.

사용 중인 자원을 비트로 표현하면 0이 하나라도 있는 바이트를 찾기 위해 배열을 검색할 수 있다.

일단 이런 바이트를 찾으면 한 번 더 1인 비트나 0인 비트를 찾아내야 하지만 그렇더라도 각비트를 하나씩 검사하는 것 보다 훨씬 효율 적이다.

 

 

비트맵의 사용

비트맵은 픽셀에 사용된다.

비트맵은 픽셀(Pixel)에 있는 비트의 집합체로 보면 됩니다. 픽셀은 하나 하나가 각기 다른 생상정보를 가지고 있다고 생각하시면 됩니다. 서로 다른 픽셀이 조합되어 하나의 이미지가 되는 것입니다. 비트맵 방식은 이미지에 대한 정교하고 화려한 표현이 가능한 장점을 가지며 픽셀 수가 많아지면 질수록 화질이 좋아질 수 있습니다. 하지만, 용량이 커지고 확대/축소로 인한 화질 문제를 유발할 수 있다는 단점이 있습니다.

 

 

문자열

여러 문자로 이뤄진 시퀀스를 문자열(string)이라고 하는데

 

배열의 길이를 추적하는 방법은

1. 문자열 안에 길이를 저장하는 것이다.

예를 들어, 첫 번째 바이트에 문자열 길이를 넣을 수 있다.

이 방법은 잘 작동 하지만 문자열 길이가 255자로 제한된다는 단점이 있다.

 

2. C는 다른 접근 방법을 사용한다.

C는 다른 언어와 달리 문자열을 위한 전용 데이터 타입을 제공하지 않는다.

대신 1차원 바이트 배열을 사용한다.

문자열이 문자 배열이기 때문에 C에서 1바이트를 나타내는 데이터 이름이 char가 됐다.

하지만 C는 문자열 길이를 저장하지 않는다는 점이 다르다.

대신에 문자 배열에 들어 있는 문자열 데이터의 끝에 바이트를 하나 추가하고, 여기에 문자열의 끝을 표시하는 문자(문자열 터미네이터)로 NUL을 넣는다.

C는 아스키 NUL문자, 즉 0을 문자열 끝을 표시하는 문자(문자열 터미네이터)로 사용한다.

이 방법은 아스키와 UTF-8 문자열에서 모두 사용할 수 있다.

 

0 1 2 3 4 5 6
C h e e s e NUL

위 표는 C언어의 문자열 저장방식과 문자열 끝 표시 방식이다.

그림을 보면 길이는 6이지만 실제로는 7바이트를 사용했음을 알 수 있다.

(문자열 끝 을 표시하는 문자에 1바이트가 더 쓰였기 때문에) 

 

명시적으로 길이를 사용하지 않고 문자열 터미네이터를 사용하는 방식에는 장단점이 있다.

장점

   - 저장이 쉽다.

   - 문자열의 끝까지 각 문자를 출력하는 일을 할 때 부가 비용이 들지 않는다는 점도 장점이다.

단점

   - 문자열 길이를 알아내려면 문자열 터미네이터를 발견할 때까지 문자열을 스캔하면서 문자 수를 세야한다.

   - 문자열 중간에 NUL 문자를 넣고 싶을 때는 이 방법을 사용할 수 없다.

 

참고로 NULL은 라이브러리에서 #define으로 정의되어 있고

NUL은 아스키 코드표에서 0을 지칭하는 차이가 있다.

쓰임에서는 차이가 없다.

 

 

복합데이터 타입

복합 데이터란 여러개의 데이터로 나누어 질 수 있는 데이터

ex) 구조체, 배열

구조체(structure) : 타입이 다른 데이터를 하나로 묶는 방법

배열(array) : 타입이 같은 데이터들을 하나로 묶는 방법

 

프로그래밍을 하다 보면 서로 다른 타입의 데이터를 묶어서 관리해야 할 일이 많이 생긴다.

구조체는 그런 데이터를 이름을 붙여서 필드로 관리하게 된다.

예를 들어 학생을 나타내는 구조체라면 이름, 나이, 점수를 가질 수 있는데

이름은 문자열이고 나이는 int, 점수는 double로 표시되어야 한다면 구조체로 이들 세 개의 값을 묶어서 관리하면 편리하다

ex)

struct student {

     char name[10];

     int age;

     double scoreAvg;

}

 

단점으로는 구조체의 크기가 클 수록 시간이 많이 걸리므로 포인터를 사용하는 것이 바람직하다

다만 포인터도 장단점이 있다.

 

 

구조체 메모리 사이즈 계산

규칙 A.

각각의 멤버를 저장하기 위해서는 기본 4바이트 단위로 구성된다.(즉 4의배수 단위) 이것은 단적인 예로 char 데이터 1개를 저장한다고 가정할때 이 1개의 데이터를 읽어오기 위해서 그 데이터가 저장되어 있는 1바이트를 읽어오는 것이 아니다. 실제로는 그 데이터가 포함된 4바이트(1 WORD 단위)를 읽기 때문이다. 그렇게 해야 속도가 빨라진다.

 

규칙 B.

구조체 각 멤버중에 가장 큰 멤버의 크기에 영향을 받는다.

 

 

예시 1)

typedef struct student

{

     char a;

     int b;

}S;

a는 1바이트 b는 4바이트지만, 실제로는 아래처럼 된다. 이것은 A의 규칙이 적용되어 a를 저장하기 위한 공간은 비록 1바이트 이지만 3바이트의 여유공간을 두게된다.

 

예시 2)

typedef struct student

{

     char a;

     char b;

     int c;

}S;

a는 1바이트 b는 1바이트, c는 4바이트이다. 이런 경우에는 총 8바이트가 된다.

 

예시 3)

typedef struct student

{

     char a;

     int c;

     char b;

}S;

 

a는 1바이트 b는 1바이트, c는 4바이트이다. 이전의 예와 구성이 같고 순서는 다르다. 그렇다면 8바이트일까? 실제로는 12 바이트가 된다. 아래의 그림을 보자.

즉 여기까지 보면 구조체를 선언할 때는 같은 자료 타입이지만 배열하는 순서에 의해 할당되는 메모리 공간이 달라짐을 알 수 있다. 따라서 같은 데이터끼리 작은 자료형을 앞에다가 선언하는 것이 유리해진다.

 

 

예시 4)

typedef struct student

{

     char a;

     double b;

}S;

a는 1바이트 b는 8바이트이다. 이럴때는 어떻게 될까? a를 4바이트에 저장하고 b를 8바이트에 저장하는 것이 아니라 double타입이 8바이트이기 때문에 기본적인 공간을 8바이트로 잡게된다. B의 규칙을 따르는 예이다.

 

예시 5)

typedef struct student

{

     char a;

     int c;

     double b;

}S;

 

마지막으로 위와 같은 형태를 보자.

a는 1바이트인데 4바이트를 사용할 것이고 c는 4바이트인데, b가 8바이트이다.

그렇다면 a도 바로 위의 예처럼 8바이트, c도 8바이트 b도 8바이트 그럼 24바이트?...? 는 당연히 아니다. 언뜻 생각해도 낭비가 심해보인다. 우선 b가 8바이트 이므로 규칙 B를 따라서 기본적인 공간은 8바이트로 잡힌다. 그런데 a와 c만 있다고 본다면 알겠지만 당연히 a는 4칸, c도 4칸이 될 것이다. (위의예). 그렇다. a와 c는 8바이트(8칸)으로 해결이 가능한 것이다. 이런 경우에는 아래 그림처럼 되며 A규칙과 B규칙이 모두 적용되는 것이다.

 

 

 

 

참고자료

https://courage1.tistory.com/41

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=sharonichoya&logNo=220495444611