unsigned 와 signed를 사용한 출력 값 비교 (제로확장, 부호확장)

signed char 정수 값, signed를 생략해도 상관없다. ( -127 ~ 127)

unsigned char - 양수 값 출력, (0~255)

unsigned int (0~4,294,967,295)

 

다음의 예제를 보자

 

#include <stdio.h>

int main()
{
    unsigned char char_num;
    unsigned short short_num;
    unsigned int int_num;

   //char char_num;
   //short short_num;
  //int int_num;


   char_num = -1;
   short_num = -1;
   int_num = -1;

   printf("char_num=[%d],short_num=[%d],int_num=[%d]\n",char_num,short_num,int_num);
   short_num = char_num;
   printf("char_num=[%d],short_num=[%d],int_num=[%d]\n",char_num,short_num,int_num);
}

 

signed01.png

의 결과가 나타난다.

 

 

그냥 signed 로 출력 했을 경우도 확인하자

 

signed02.png

 

sNum=cNum을 대입한 경우 이 값이 -1이 나온 것에 대해 생각해 보자.


char의 값 -1의 경우는 unsigned에서 255의 값으로 출력되었으며 이것은 우리가 알고 있는 사실과 동일하다. unsigned는 수를 양수로만 표현해 주며 따라서 0부터 255까지의 값을 가지는 char 1byte 정수형의 경우에 -1의 값은 255와 같다.


그런데 왜 signed 형에는 같은 -1을 대입했는데 결과 값이 다른 것일까?


그 이유가 부호 확장에 있다.


short sNum = char cNum 에서 cNum은 char 형이기 때문에, 묵시적인 형 변환이 발생하게 되는데 이때, char형 데이터인 cNum을 바로 short형 데이터 sNum에 넣는 것이 아니라 cNum을 2바이트 크기로 확장을 하게 된다.


1바이트에서 2바이트로 확장을 하면서 나머지 빈 공간에는 음수면 1로 채우고 양수면 0으로 채우게 된다.


따라서 (signed) char 인 a변수는 앞에 1을 채워서 1111 1111 1111 1111가 되고, unsigned char 인 cNum 변수는 앞에 0을 채워서 0000 0000 1111 1111가 되는 것이다.


그렇다면 부호 확장은 무엇일까? 부호 확장이란 데이터의 비트 크기를 확장하는 것이다.
위의 경우처럼, 8비트를 16비트로 만드는 것을 말할 수 있겠다.

양수 값의 부호 확장에는 상위 자리 0으로 채우고,
음수 값의 부호 확장에는 상위 자리를 1로 채우게 된다.

 

signed03.jpg

 

즉, 부호 확장으로 1바이트의 char 변수 값 -1이 2바이트의 short 변수 값에 대입 되면서 앞쪽에 1바이트의 빈 공간이 생기게 되고 signed와 같은 경우는 부호비트를 가지므로 부호에 따라 음의 값(1)의 최상위 비트를 가졌던 cNum = -1은 sNum에 대입되면서 앞쪽의 1바이트 공간에 1을 채우게 되어 1111 1111 1111 1111 의 값을 가지므로 -1이 표시되게 된다.


물론 unsigned의 경우에는 부호비트가 존재하지 않기 때문에(unsigned는 양수로만 표현되게 한다.) 부호 확장이 생기지 않으므로 더 큰 바이트를 가지는 변수에 대입하더라도 그대로 표시된다.