본문 바로가기
코스웨어/14년 스마트컨트롤러

2014년 3월11일 업무일지 김대희

by 알 수 없는 사용자 2014. 3. 11.
728x90
반응형

비트연산자란 <-클릭하면 원문이동



  • CPU를 구성하는 3가지

 ALU(arithmetic logic unit)

산술논리장치.

 CU(control unit)

장치를 제어하는 회로

레지스터(register) 

CPU와 동급으로 동작하는 CPU의 내부memory지만 가격이비쌈

기억하고 cpu를 동작,연산시킬 수 있는 특수목적 레지스터도있고

오직 기억만 할수있는 레지스터가 있다


레지스터에서 1bit를 기억시키는 회로가 플립플롭(flip-flop)









  • & (bit AND),  | (bit OR)

&& - AND

& - bit AND


|| - OR

| - bit OR



비트연산자는 각 비트를 연산한다

#include <stdio.h>
int main()
{
  int num1 = 3;
  int num2 = 4;
  int num3;

  num3 = num1+num2;
  printf("num1 + num2 = %d\n",num3);

  num3 = num1&&num2;
  printf("num1 && num2 = %d\n",num3);

  num3 = num1&num2;
  printf("num1 & num2 = %d\n",num3);

  return 0;

 

결과 : 

num1 + num2 = 7

num1 && num2 = 1

num1 & num2 = 0




num1과 num2에 있는 값 3,4를 각각 2진수로 변환

비트단위로 true, false를 연산한다


3과 4는 true지만

비트단위로 쪼개 연산하는 bit AND연산자를 사용하면 결과는 다르다






  • 틸드 ' ~ ' (bit NOT)

틸드는 한비트씩을 전부 반대로 바꾸어놓음

1111 0000 이라면

0000 1111로 바꿔놓는다


~(틸드)는 bit NOT이라고도 할 수 있다

일반 NOT은 ' ! ' 연산자를 사용하지만 틸드는 '~' 연산자를 사용한다


FFFFFFF0(16) = 1111 1111 1111 1111 1111 1111 1111 0000(2) 에서 틸드를 사용하면

0000000F(16) = 0000 0000 0000 0000 0000 0000 0000 1111(2)로 바꾸어 놓는다


~0 

1을반환 

~1 

0을반환 


예)

#include <stdio.h>
int main() 
{  /* bit NOT (틸드) */

  int num1 = 15// 2진수로 1111
  int num2 = ~num1;

  printf("~num1 = %d\n",num2);



  return 0;

} 

결과 : 

~num1 = -16



10진수 15는 2진수로

1 

1 

1 

1 

이다


이것에 bit NOT을 적용하면

0 

0 

0 

이 된다


위의 수를 2의보수로 계산하면

0000 0000 0000 0000 0000 0000 0001 0000 -> 16


그래서 -16







  • ' ^ ' 비트단위 XOR(Exclusive OR)

1과0이 서로 달라야지만 '1'을 반환한다


1011

0110 이라면

1101 이 된다


- bit XOR -

1 

1 

0 






  • 비트이동(Shift)

'<<', '>>'를 Shift연산자라고 한다

비트를 주어진 값만큼 이동 할 수 있다




  • >> 오른쪽으로 비트이동

#include <stdio.h>
int main() 
{  
  int num = 10;
  int result;

  printf("비트이동전 : %d\n",num);  

  result = num>>1;

  printf("비트이동후 : %d\n",result);  

  return 0;

} 

결과 : 

비트이동전 : 10

비트이동후 : 5


비트 이동후 5가 나온이유는 다음그림 참조

2진수 1010 = 10진수 10 이므로..

2진수 101 = 10진수로 5이다.


만약 >>2 를 했다면 2칸이 이동되서 '2'가 나올것이고

>>3 를 했다면 3칸이 비트이동해 '1'이 나왔을 것이다.







  • << 왼쪽으로 비트이동

#include <stdio.h>
int main() 
{  
  int num = 30;
  int result;

  printf("비트이동 전 num : %d\n",num);

  result = num << 1;
  printf("<<1 이동 후 num : %d\n",result);
 
  result = num << 2;
  printf("<<2 이동 후 num : %d\n",result);


  return 0;

} 

결과 : 

비트이동 전 num : 30

<<1 이동 후 num : 60

<<2 이동 후 num : 120


그림으로 설명하면 아래과 같은



위 사실을 통해 비트 1칸을 왼쪽으로 이동할 수록 정수의 값이 2배가 된다는걸 알 수 있다

위를 예제로 보았을 때 맨 왼쪽에 1이라는 값이 있었다고 가정하면

왼쪽으로 비트이동 할때마다 하나씩 떨어져 나간다.


반대로 비트를 오른쪽으로 >>이동 했을시 정수에 2를 나눈다는 것을 알수있다

CPU는 이런 비트연산으로 더 좋은성능을 발휘한다


만약 나누었을때 떨어지지않고 나머지가 있다면, 몫을 반영한다






  • singed int와 unsigned int의 비트이동

#include <stdio.h>
int main() 
{  
  signed int iNum; //sign (부호)를 쓰는 정수
  unsigned int uiNum; //Unsigned(부호를 쓰지않는 양수)

  iNum = 0xFFFFFFFF;
  uiNum = 0xFFFFFFFF;

  printf("iNum = %X\n",iNum);
  printf("uiNum = %X\n\n",uiNum);

  iNum = iNum>>1;
  uiNum = uiNum>>1;

  printf("iNum = %X\n",iNum);
  printf("uiNum = %X\n",uiNum);

  return 0;

} 

결과값 : 

iNum = FFFFFFFF

uiNum = FFFFFFFF


iNum = FFFFFFFF

uiNum = 7FFFFFFF




int와 Unsigned int가 있다 이둘의 값은

애초에 FFFFFFFF로 초기화를 시켜놓고


둘다 같은방법으로 비트를 1씩 오른쪽으로 밀어버렸더니 값이 달라졌다

그이유는


int 앞에는 signed 라는 수식이 생략되어있다

부호를 적용한다는 뜻으로 음수와 양수를 모두 사용하는 자료형이다

그리고

unsogned int부호는 사용하지않고 오직 '양수'로만 표현하겠다는 자료형이다


비트이동을 하면 다음과 같다


int iNum = FFFFFFFF 와 unsigned int uiNum = FFFFFFFF 은 2진수로 표현하면 아래와 같다

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

이 둘에게 ' >>1 '비트이동을 시키면 다음과 같다



>>1 을 적용 시킨 후.


signed int iNum

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 


unsigned int uiNum

0

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 

1 


signed int는 부호비트를 사용하고 애초에 부호비트에 1(음수)가 있었으므로 비트이동을 하면 1(음수)가 채워진다

unsigned int는 앞에 부호비트를 사용하지않으므로 비트이동을 하면 빈자리에는 0이 들어간다














  • 비트연산자 총정리 소스코드

#include <stdio.h>
int main() 
{
  int iNum1;
  int iNum2;
  int iNum3;

    /* bit OR */

  iNum1 = 0xB; //10진수로 11
  iNum2 = 0x4// 4
  iNum3 = iNum1 | iNum2; //bit OR

  printf("%X\n\n",iNum3);

    /* bit AND */

  iNum1 = 0xB;
  iNum2 = 0x4;
  iNum3 = iNum1 & iNum2; //bit AND

  printf("%X\n\n",iNum3);

    /* bit NOT */

  iNum1 = 0xFFFFFFF0;
  iNum3 = ~iNum1; //틸드..비트단위를 반대로 바꾸어놓음

  printf("iNum1 = %X\n",iNum1);
  printf("iNum3 = %X\n\n",iNum3);

    /* bit XOR */

  iNum1 = 0xB; // 10진수로 11
  iNum2 = 0x6// 6
  iNum3 = iNum1 ^ iNum2; //bit XOR

  printf("iNum1 ^ iNum2 = %X\n\n",iNum3); // D (10진수로13)

    /* 비트이동(Shift연산자)  */

  iNum1 = 0x18 >> 1//비트를 오른쪽으로 1칸 밀어라
  iNum2 = iNum1 >> 1;
  iNum3 = iNum2 >> 2;

  printf("iNum1 = %X\n",iNum1);
  printf("iNum2 = %X\n",iNum2);
  printf("iNum3 = %X\n",iNum3);

  iNum3 = iNum3 << 3//비트를 왼쪽으로 3칸 밀어라
  printf("\niNum3 = %X\n",iNum3);


  return 0;

} 

결과 : 

F


0


iNum1 = FFFFFFF0

iNum3 = F


iNum1 ^ iNum2 = D


iNum1 = C

iNum2 = 6

iNum3 = 1


iNum3 = 8




-------------------------------------------------


변수와 상수 <-클릭하면 원문 이동


변수와 상수는 반대개념

변수는 변하는 값

상수는 변하지 않는 값


int num = 3; 에서

num은 변수고 '3'은 상수다



  • l-value와 r-value

#include <stdio.h>
int main()
{
  int iNum = 3;

  iNum = 100// ' = '을 기준으로 iNum쪽은 L-Value, 100쪽은 R-Value라고 한다

  100 = 3//컴파일에러

  printf("iNum = %d",iNum);


  return 0;

} 

결과 : (컴파일에러)

Microsoft (R) 32비트 C/C++ 최적화 컴파일러 버전 16.00.30319.01(80x86)

Copyright (c) Microsoft Corporation. 모든 권리 보유.


test.c

test.c(8) : error C2106: '=' : 왼쪽 피연산자는 l-value이어야 합니다.


---------------------------------------------------------------------



3을 100에 대입할 수는 없다..

100의 자리에는 L-valuse..즉, 변수가 들어가야하기에 컴파일 에러


l-value에는 메모리가 입력되어야 한다 그게 변수다


메모리 어딘가에 변수가 있다 어디에 있냐하면 그 변수가 위치한 주소값이 따로 CPU에 존재한다.







  • 변하지 않는 변수 - 상수

#include <stdio.h>
int main()
{
  int iNum = 3;
  const int ciNum = 100;

  iNum = 100// ' = '을 기준으로 iNum쪽은 L-Value, 100쪽은 R-Value라고 한다
  ciNum = 1000//const int에 값을 바꿀 수 없음 ( 상수 )  

  printf("iNum = %d\n",iNum);
  printf("ciNum = %d\n",ciNum);


  return 0;

} 

결과 : (컴파일에러)

test.c(8) : error C2166: l-value가 const 개체를 지정합니다.


--------------------------------------------------------



ciNum은 read only이다 읽기전용이다

const int는 선언과 동시에 초기화 하지 않으면

다음 구문에서 값을 넣어줄 수가 없다 변수가 잠겨있다고 생각하면 된다





즉, 다음과 같은 실수를 하면 안된다

#include <stdio.h>
int main()
{
  int iNum = 3;
  const int ciNum; 
  
  /*const int선언을 하고 세미콜론(;)으로 닫아버리면,
  ciNum에 값은 이제 더이상 넣을 수 없다 */


  ciNum = 1000//택도없음

  printf("ciNum = %d\n",ciNum);


  return 0;

} 

결과 : (컴파일 에러)





------------------------------------------------------------------


자료형의 범위 <- 클릭하면 원문이동




  • 자료형의 종류와 범위



  • sizeof(자료형 또는 변수)

#include <stdio.h>
int main()
{

  printf("int         : %d\n",sizeof(int));

  printf("float       : %d\n",sizeof(float));

  printf("char        : %d\n",sizeof(char));

  printf("long        : %d\n",sizeof(long));

  printf("long long   : %d\n",sizeof(long long));

  printf("double      : %d\n",sizeof(double));

  printf("long double : %d\n",sizeof(long double));

  return 0;

} 

결과 : 

int         : 4

float       : 4

char        : 1

long        : 4

long long   : 8

double      : 8

long double : 8

------------------------


자료형의 크기 (byte)단위를 10진수로 출력했다

int는 4byte이며 double은 8byte 등 자료형의 크기를 간단히 출력


위와같이 sizeof() 연산자를 이용하면 각 자료형의 범위를 볼 수 있다

*sizeof() 는 함수가 아닌 연산자다





  • 다음을 살펴보자

#include <stdio.h>
int main() // sizeof
{

  int num1 = 2;
  int num2 = 4;

  printf("sizeof(num1+num2) = %d\n",sizeof(num1+num2));


  return 0;

} 

결과 : 

sizeof(num1+num2) = 4


int형은 4바이트이고 sizeof연산자를 이용해 int형인 num1과 역시 int형인 num2를 각각 더한 값은 출력하려 했다

결과는 6이나 8이 아닌 4로 나왔다


sizeof(num1+num2) 에서 num1+num2는 연산하면 '6'이다 그래도 4가 나오는 이유는

sizeof 연산자 자체는 자료형의 크기를 비교하는 연산자이기 때문이다


괄호 안의 연산은 쉽게말해 2+4 이기때문에 이것부터 연산하고..

num1(2)과 num2(4)를 더한 수는 6인데

이 '6'또한 int형 정수이기 때문에 int 6에 대한 자료형의 크기가 sizeof에 들어가게되어 결과는 '4'가 나온다.





  • 변수네 넣지 않은 실수를 sizeof 하면 float인 4byte가 출력될까, double인 8byte가 출력될까?

#include <stdio.h>
int main() // 실수의 자료형을 sizeof하면 double로 인식
{

  printf("sizeof(2.3) = %d\n",sizeof 2.31);

  return 0;

} 

결과 : 

sizeof(2.3) = 8





여기까지 틀린부분 있으면 지적바랍니다

감사합니다


티스토리 주소 : http://euro87.tistory.com/







728x90