맨위로

C PROGRAMMING - 기초2012. 8. 25. 15:09

안녕하세요 ? 이번 강의에서는 C언어의 자료형(Data Type)과 변수,연산자,수식 그리고 상수 에대해서 알아보도록 하겠습니다.이번 강의 부터 글의양이 전에 글들보다 많습니다. 그래서 글의 흐름이 약간 뒤엉킨 부분이 있을수 있으니 양해 해주시기 바랍니다. 먼저 강의를 시작하기전에 이블로그에 와주신 모든 분들께 감사의 말씀드립니다.


자료형(Data Type)과 변수,연산자,수식 그리고 상수

먼저 형,연산자,수식이 무엇인지 프로그램에 사용되는 가장 기본적인 데이터인 변수와 상수를 통해서 알아보도록 하겠습니다.

  • 형(Type) : 변수와 상수들이 취할값과 그것에 가해질수 있는 연산을 결정한다.

  • 연산자 : 변수와 상수를 어떻게 연산할지를 결정한다. (+,-,*,% 등)

  • 수식 : 변수와 상수를 묶어 새로운 결과를 나타낸다.

이번글에서 배워볼것들입니다. 이번글에서 차례대로 알아보도록 하겠습니다. 먼저 형,연산자,수식에 대한 설명을 하기전에 변수에 대해서 간단히 알아보도록 하겠습니다.


변수

지난 강의에서 살펴본부분과 오늘 변수에 대해서 살펴볼 부분을 정리한 내용은 다음과 같습니다.

  • 변수는 '선언' 합니다.

  • 변수는 다음과 같은 형태로 선언합니다. (int val : val이라는 이름의 변수를 선언하며 이변수는 int 형으로 데이터를 저장 및 참조 해야한다.

  • 변수와 상수명의 첫글자는 반드시 영문이며 대문자와 소문자는 구분됩니다. ( int val2(o) int 2val(x) / int val ≠ int VAL )

  • int ,float ,if 같은 C언어 예약어는 변수명으로 사용 할 수 없다 ( int if (x) ) 

  • 긴 문장에는 "_" 를 사용해서 알기 쉽게 한다 ( "_"도 문자로 취급한다. )

  • 변수명에는 사용목적에 알맞은 이름을 붙히고 지역변수는 짧은이름 외부변수에는 가능한 긴이름을 쓴다.

변수에 대해서 모르시는 분들은 " 

C언어 - 변수와 수식표현① / 

C언어 - 번수와 수식표현②" 강의를 참고 해주시기 바랍니다.

위의 6가지 중 밑에 2가지는 선택사항입니다. 하지만 가능한 다음과 같이 해주는게 좋습니다. 이제 본격적인 주제中에 형부터 시작하겠습니다. 


데이터 형과크기

C언어에는 기본적인 데이터 형이 있습니다. 기본적인 데이터 형은 다음과 같습니다.

  • char : 한바이트문자 (8비트)

  • int : 정수 (32비트)

  • float : 단정도(single - precision) 부동소수점 (소수점이하 정밀도 6자리 이상)

  • double : 배정도(double - precision) 부동소수점 (소수점이하 정밀도 10자리 이상)

char val,val2;  /  int val3,val4;


이 기본데이터 형에는 경우에 따라 한정사가 붙을수 있는데 정수형에는 short 와 long 을 쓸수있습니다.

  • short int val1;            / short 16비트

  • long int val2;             / long 32비트
이런 경우 int는 보통 생략됩니다.


문자나 정수에는 부호형(signed) 또는 무부호형 (unsigned) 라는 한정사를 붙힐수 있습니다. 무부호형은 항상 0이상이며  미만으로 결정됩니다. 만약에 8비트 이면 0 ~ 255의 값을 갖습니다. 무부호형은 다음과 같습니다.


 unsigned char

 8 비트

0 이상 255 이하 

 unsigned short

 16 비트

0 이상 65535 이하

 unsigned int

 32 비트 

0 이상 4,294,967,295 이하 

 unsigned long

 32 비트

0 이상 4,294,967,295 이하

unsigned 를 빼고 signed 를 붙히고 선언하면 부호형이 됩니다. 일반적은 signed int 는 int 와 같으므로 signed 는 생략 합니다. 부호형의 범위는 다음과 같습니다. (참고만 하시길 바랍니다.)


 char

8 비트 

-128 이상 127 이하 

 short

16 비트 

-32768 이상 32767 이하 

 int 

32 비트 

-2,147,483,648 이상 2,147,483,647 이하 

 long

32 비트 

 -2,147,483,648 이상 2,147,483,647 이하


상수 (정수형,실수형)

일단 상수에 대해서 간단히 알아보도록 하겠습니다. 일단 상수는 변경이 가능한 변수와달리 변경이 불가능 한수입니다. 상수에는 두가지 종류가 있는데 바로 정수형상수와 실수형상수 입니다. 정수형,실수형상수는 다음과 같습니다.

  • 정수형 상수는 int 형으로 표현합니다.

  • 실수형 상수는 double 형으로 표현합니다.


1234 같은것이 정수형 상수 int 이며 (int val = 1234;) 3.14 같은것이 실수형 상수입니다. 실수형으로 선언시 double 형으로 표현됩니다. 여기서 float 형을 쓰게된다면 (float val2 = 3.14;) 라고 쓰면 3.14는 double 형이됩니다. 이렇게 쓰면 데이터가 잘려나갈수도 있습니다. 이것을 방지하기 위해 상수뒤에 접미사를 붙혀서 해결할수 있습니다. 

float val2 = 3.14f


위와 같이하면 3.14는 float 형이됩니다. 이처럼 정수형 상수에는 접미사를 붙힐수 있습니다. 접미사의 종류는 다음과 같습니다.


일반적으로 char형과 short 형변수에 대한 접미사는 정의되어 있지 않습니다.


정수값은 8진수나 16진수로 표기할수 있습니다. 표기 방법은 다음과 같습니다.

  • 8진수 : 0이 앞에 나온다 ex) 10진수 : 31 => 8진수 : 037


  • 16진수 : 0x 혹은 0X가 앞에 나온다 ex) 10진수 : 31 => 16진수 : 0x1f

8진수나 16진수도 뒤에 접미사를 붙혀 long 이나 unsigned 로 만들수 있습니다.


상수 (문자형)


상수에는 정수형,실수형 상수말고 문자상수가 있습니다. 문자상수는 ''(작은 따옴표) 안에 하나의 문자로 나타내며 정수 값을 가지게 됩니다. 밑에 ASCII 코드표를 보면 알수 있듯이 'A' 는 41 이라는 값을 같게 됩니다. 숫자 연산도 물론 할수 있습니다. 

출처:위키피디아

문자는 이스케이프 시퀸스(Escape Sequence)를 통해서도 나타낼수 있습니다. 이스케이프 시퀸스는 별도의 기능을 제공하는 문자이며 그종류는 다음과 같습니다.  

Escape Sequence

의미 

\ooo ( \013 )

아스키 문자 8진수 표시 

\xhhh ( \x7 ) 

아스키 문자 16진수 표시 

\a

경고음 

\b

백스페이스  ( backspace ) 

\f

폼 피드 ( form feed ) 

\n

개행 ( New Line ) 

\r

캐리지 ( Carriage return ) 

\t

수평 탭 

\v

수직 탭 

\'

작은 따옴표 출력 

\"

큰 따옴표 출력 

\?

물음표 출력 

\\

역슬래쉬 출력 

\0

null 문자 

위의 이스케이프 문자들은 외우실 필요는 없고 프로그래밍을 할때 참조만 하시길 바랍니다. 

상수에는 하나의 문자만을 나타내는 문자상수말고 문자열을 나타내는 문자열 상수 (string contant) 가 있습니다. 문자열 상수는 다음과 같이 큰따옴표를 붙혀서 사용합니다. 

  • "Hello,World"  /* "" 큰 따옴표는 문자열에 포함되지 않습니다.


  • "" /* 빈문자열 상수 */


  • "Hello","World" /* 문자열 상수 연결 , 출력값 : Hello,World

문자열 상수에도 문자상수에 쓰던 이스케이프 시퀸스도 사용할수있습니다. 위의 사용예를 보면 문자열과 문자열을 연결할수  도 있습니다. 이것을 이용해서 긴문장을 여러라인에 보기 쉽게 쓸수 있습니다. 이러한 문자열 상수를 슬대 주의할점이 있습니다. 일단 문자열 상수는 문자의 배열입니다. ( C언어 - 배열 참조 ) 문자 배열은 그끝에 '\0' 을 가지고 있습니다. 그래서 문자열 상수에서는 따옴표 안에 문자수보다 한개가 더필요하게 됩니다. "Hello" 라는 문자열이 있다면 다음과 같이 됩니다.


 H

\n 


보면 알수 있듯이 실제로 필요한 기억장소는 '\0' 을 포함한 갯수가 됩니다.

다음 또 주의할점이 있습니다. 문자상수와 문자열 상수가 구분해서 사용해야 한다는 점입니다. 이말은 다음과 같습니다. 

'h' 라는 문자상수와 "h" 문자열 상수가 구분되어서 사용된다는 말입니다. 'h'는 h를 나타내는 정수이고 "h"는 배열로 표현되며 h와 '\0' 으로 이루어져있습니다. 이점을 구분해서 사용해야합니다.


상수의 열거 (참고)

상수에는 열거라는 형식이 있습니다. 일단 열거는 다음과 같은 형태입니다.

enum 상수명 {값1,값2 };

열거는 정수형 상수를 열거한 것입니다. 열거의 값을 지정하지 않으면 값1은 0 값2 는 1의 값을 얻고 그뒤에 수도 차례되로 값을 얻게 됩니다. 만약 다음과 같이 값이 지정되 있으면 다음값은 그값을 기준으로 바뀌게 됩니다.

enum alp {A =1,B,C,D,E,F,G,H,I,J,K};

/* A=1 , B=2 , C=3 , D=4 ,E=5 …………… J=10 , K=11 */

열거의 상수명은 무조건 달라야 됩니다. 하지만 값은 같아도 됩니다.


선언문

변수들은 사용되기전에 선언되어야 합니다. 이런 변수들은 선언하는것이 선언문입니다. 선언문을 통해선언할때 형을 지정하고 변수이름을 나열해 선언합니다. 

int num,sum,i;

char s[100];

위의 리스트형식은 다음과 같이 쓸수도 있습니다.

int sum;

int num;

int i;

char s[100];

사용하기 편한것을 사용하시면 됩니다. 

변수는 다음과 같이 초기값을 지정하며 선언할수 있다. 다음과 같이 등호와 수식이 붙으면 초기화 하는 역활을 합니다.

char i = '\\' ;

int num = 0;

int sum = MAXLINE +1;

변수는 프로그램이 실행시작전에 한번실행됩니다. 초기화는 상수의 수식이어야 합니다. (지역 변수는 실행시작전에 초기화 되지 않습니다. 초기화 되는 지역번수는 함수나 블록에 처음들어 갈때 초기화 됩니다. 초기화 되지 않는 지역변수는 정의되지 않습니다. ) 만약 따로 지정되지 않은 외부 변수는 정적변수는 초기화 되면 0으로 초기화됩니다. 

만약 변수값이 변하는 것을 원치 않는다면 const 라는 한정사를 사용하면 됩니다.

const 데이터형 변수명 = 변수값

const duble s = 3.141592;

const char s[] = "Hello";


산술연산자

이제 연산자에 대해서 알아보도록 하겠습니다. 먼저 산술연사자 부터 알아보도록 하겠습니다. 산술연산자의 종류는 다음과 같습니다. 

  • + . - . * . / . % (나머지 연산자)


몇가지 예를 들며 주의할점을 알아보겠습니다. 먼저 다음의 표현의 결과를 예측해보겠습니다. 

5/9

일반적인 계산기로 연산한 결과 0.5556이 나오게됩니다. 하지만 C언어에서의 위의 연산을 계산하게 되면 0이라는 결과가 나오게됩니다. 0 이라는 결과값이 나오게 되는이유는 C언어의 연산특징과 관련이있습니다. 그특징은 다음과 같습니다. 

C언어는 정수와 정수사이에 연산값은 정수값만을 출력하게 됩니다. 

C언어는 실수와 실수사이에 연산값은 실수값만을 출력하게 됩니다.

위의 특징으로인해서 5라는 정수와 9라는정수의 연산값은 0.5556이라는 실수값을 출력하지못하고 0이라는 정수값을 출력하게 됩니다.  만약 실수값을 얻고 싶다면 실수와 실수로 연산을 다음과 같이 해주시면 됩니다. 

5.0/9.0

이제 사칙연산과 다르게 약간 생소하실수 있는 % 나머지 연산자에 대해서 알아보도록 하겠습니다. %연산자는 나머지를 나타내는 연산자 입니다. 다음과 같은 형태이며 X를 Y로 나눈값의 나머지를 출력하게 됩니다. 

X % Y 

예를 들어서 20%5와 17%5 를 연산해 보겠습니다. 20%5는 나누어 떨어지므로 0이라는 결과값이 출력됩니다. 그러나 17%5 는 나머지가 2가 되므로 2가 출력이 됩니다.  (참조: 나누어 떨어진다.)

 

<그림 1>

이 나머지 연산자는 float 나 double 에 적용되지 않고 음수에도 적용되지 않습니다.  나머지 연산사용시 이점주의 하시기 바랍니다. 

이런점외에 몇가지 주의점이 더있지만 지금은 이정도만 알아보고이제 관계연산자와 논리 연산자로 넘어가겠습니다.


관계연산자와 논리연산자

먼저 관계연산자에 대해서 알아보도록 하겠습니다. 일단 관계 연산자의 종류는 다음과 같습니다. 

> ,  >=  ,  <  ,  <=  ,  ==  ,  !=

위의 연산자들에 대해서 간단히 알아보면 다음과 같습니다. 

 연산자

연산자의 기능 

결합방향 

우선순위 

>

 n1 > n2

n1 이 n2 보다 큰가 

 

모두 같음

(산술연산자

보다 낮음)


 >=

n1 >= n2 

n1 이 n2 보다 같거나 큰가 

n1 < n2 

n1 이 n2 보다 작은가 

<= 

n1 <= n2 

 n1 이 n2 보다 같거나 작은가

== 

n1 == n2 

n1 이 n2 와 같은가 

 !=

n1 != n2 

n1 이 n2 와 다른가 

관계연산자는 크기 및 동등관계를 따지는 연사자입니다. 비교하는 기능이므로 '비교 연산자' 라고도 부릅니다. 관계연산자들은 참이면 1 , 거짓이면 0 을 연산결과로 내놓습니다. 다음코드를 통해 확인 해보겠습니다.

#include <stdio.h>

int main(void)

{

int n1 = 10;

int n2 = 12;

int result1,result2;


result1 = (n1 == n2);

result2 = (n1 <= n2);


printf("n1이n2와같은가? %d\n",result1);

printf("n1이n2보다같거나작은가? %d\n",result2);

return0;

}


출력결과는 다음과 같습니다. 

n1이n2와같은가? 0
n1이n2보다같거나작은가? 1

관계연산자는 산술연산자 보다 우선순위가 낮습니다. 만약 다음과 같은식은 우선순위로 인해 i < (lim -1)이됩니다.

i < lim -1 


i < (lim -1)

우선순위에 대해서는 글뒤에서 배우게되지만 여기서는 위의 표에 우선순위가 무엇을 말하는지에 대한 간단한 설명입니다.

이제 논리연산자에 대해서 알아보도록 하겠습니다. 논리연산자도 참과 거짓을 따지는 연산자이며 다음으로 구성되어 있습니다.

&& (AND)  || (OR)  ! (NOT)

논리 연산자의 기능은 다음과 같습니다.

연산자

연산자의 기능

결합 방향

&& 

A && B 

 A와B모두 참이면 결과 참

 

||

A || B 

 A와B둘중 하나라도 참이면 결과 참 

 

!A 

 연산결과 A가 참이면 거짓 A가 거짓이면 참

 

이 논리연산자들은 참 · 거짓이 판정되면 검사를 마치게 됩니다. 다음문장을 예로 들어 보겠습니다. (getline 함수 문자를 읽어들이는 함수의 일부분)

for(i = 0; i<lim-1 && (c=getchar()) !=EOF && c!='\n'; ++i)

s[i] = c;

위문장에 쓰인 && 연산자는 결합방향이 → 이므로 i < lim-1 에 대한 검사가 참이 아니면 문자를 읽어서는 안되며 getchar 를 호출하기 전에 EOF 를 검사해도 안됩니다. 예제를 통해서 논리연산자에 대해서 더알아보겠습니다.

#include <stdio.h>

int main(void)

{

int n1 = 10;

int n2 = 12;

int r1,r2,r3;

r1 = (n1==10 && n2==12);

r2 = (n1<=12 || n2>=12);

r3 = !n1;

printf("r1 : %d\n",r1);

printf("r2 : %d\n",r2);

printf("r3 : %d\n",r3);

return0;

}

결과값은 다음과 같습니다.

r1 : 1

r2 : 1

r3 : 1

관계연산자와 마찬가지로 참이면 1 거짓이면 0을 반환합니다. 예제는 모두참이므로 1을 반환했습니다. 예제를 통해 쉽게 이해할수 있습니다.


증가 연산자 와 감소 연산자

증가연산자와 감소연산자는 말그대로 변수의 값을 증가시키거나 감소시키는 연산자입니다. 일반적으로 증가연산자 ++ 는 1을 증가시키고 감소연산자 -- 는 1을 감소시킵니다. 변수를 증가시킬때는 다음과 같이 증가연산자를 사용합니다. 

++nl;

증가 연산자에서 주목할것은 증가연산자나 감소연산자를 변수 앞에나뒤에 모두 사용할수 있다는것입니다. 예제를 통해서 알아보겠습니다. 예제는 다음과 같습니다.

#include <stdio.h>                                   /* ++num --num    */

int main(void)

{

int num = 7;

int num2,num3;

num2 = ++num1;

num3 = --num1;

printf("num1 : %d\n",num1);

printf("num2 : %d\n",num2);

printf("num3 : %d\n",num3);

return0;

}

num1 : 7

num2 : 8

num3 : 7



#include <stdio.h>                                   /* num++ num--   */

int main(void)

{

int num = 7;

int num2,num3;

num2 = num1++;

num3 = num1--;

printf("num1 : %d\n",num1);

printf("num2 : %d\n",num2);

printf("num3 : %d\n",num3);

return0;

}


num1 : 7

num2 : 7

num3 : 8

예제를 보면 쉽게 알수있지만 보퉁설명을 하면 다음과 같습니다. 

++num 은 num이 사용전에 증가하고 num++는 사용후에 증가시킵니다. 

이런 증가연산자는 오직변수에만 사용가능하며 (i+j)++와 같은 수식에는 증가,감소 연산자를 사용할수 없습니다. 다음과 같이 어디에나 붙혀도 결과값이 같은것이있다. 

if(c == '\n')

nl ++;

하지만 증가연산자를 앞,뒤위치를 신경써서 붙혀야 하는 경우도 있다. 다음예를 통해 알아보겠습니다. 다음예는 문자열 s중 문자c를 제거하는 함수인 squeeze(s,c) 입니다. 

void squeeze(char s[],int c)

{

int i,j;

for (i=j=0 ; s[i] != '\0'; i++)

if (s[i] != c)

s[j++] = s[i];

s[j] = '\0';

}

일단 이해하기 위해서 프로그램에 흐름을 알아야 됩니다. 이프로그램은 C가 아닌 문자가 나타날때마다 현재의 j위치로 복사되고 다음문자를 확인하기위해 j가 증가됩니다, 이프로그램의 부분을 다음과 같이 바꿀수있습니다.

if (s[i] != c){

s[j] = s[i];

j++;

}

다른 예인 getline 함수의 다음코드를 보겠습니다.

if (c == '\n'){

s[i] = c;

++i;

}

위의 코드는 다음과 같이 바꿀수있습니다. 

if ( c== '\n')

s[i++] = c;

위 부분을 한번에 이해 하기 쉽진않으나 몇번읽으면 충분히 이해하실수 있습니다.

비트연산자

C언어에는 6개의 비트연산자가 있습니다. 비트연산자는 비트단위로 연산을 진행하는 연산자이며 피연산자는 반드시 정수이어야 합니다. 일단 비트연산자의 종류및 기능에 대해서 알아보겠습니다.

 연산자

연산자의 기능 

결합 방향 

&

 비트단위로 AND 연산을 한다.

 →

|

 비트단위로 OR 연산을 한다.

 →

^

 비트 단위로 XOR 연산을 한다.

 →

<<

 피연산자의 비트열을 왼쪽으로 이동시킨다.

 →

>>

 피연산자의 비트열을 오른쪽으로 이동시킨다.

 →

~

 단항연산자로써 피연산자의 모든 비트를 반전시킨다.

 

각연산들에 대해서 하나씩 알아보도록 하겠습니다. 먼저 &(비트방식 AND)연산자를 살펴보겠습니다. 이연산자는 비트의 형을 뜨기 위해 사용됩니다. AND 연산자의 진리표는 다음과 같습니다.

 A

A&B 

 1

 1

 0

 0

예제를 통해 비트연산방식에 대해서 확인해보겠습니다.

#include <stdio.h>

int main(void)

{

int n1 = 15; /* 00000000 00000000 00000000 00001111 */

int n2 = 20; /* 00000000 00000000 00000000 00010100 */

int result = n1&n2; /* 00000000 00000000 00000000 00000100 */

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

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

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

return0;

}

n1 = 15
n2 = 20
result = 4

결과값을 보면 알수있듯이 피연산자는 변하지 않습니다. 이연산자는 다음과 같은 형식으로 사용해서 n의 하위 비트이외의 것을 0으로 만드는데 사용하기도 합니다.
 
n = n & 0177;

다음으로 비트방식OR연산자인 | 에대해서 알아보도록하겠습니다.  OR 연산자는 비트중 하나라도 참(1)이면 1을 반환합니다. 진리표는 다음과 같습니다. 

 A

A|B 

 1

 1

 0

 0

예제를 통해 알아보겠습니다. 

#include <stdio.h>

{

int n1 = 17; /* 00000000 00000000 00000000 00010001 */

int n2 = 14; /* 00000000 00000000 00000000 00001110 */

int result = n1|n2; /* 00000000 00000000 00000000 00011111 */

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

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

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

return0;

}


n1 = 17

n2 = 14

result = 31

OR 연산자는 다음 처럼 비트를 1로 세트시키는데 사용됩니다.

X = X | SET_ON ;

이제 비트방식 XOR 연산자인 ^에 대해서 알아보도록 하겠습니다. ^연산자는 비트값이 서로 다르면 1을 반환 하는 연산자 입니다. XOR 진리표는 다음과 같습니다.

 A

A^B 

 1

 1

 0

 0

예제를 통해서 XOR 연산을 알아보겠습니다.

#include <stdio.h>

{

int n1 = 17; /* 00000000 00000000 00000000 00010001 */

int n2 = 15; /* 00000000 00000000 00000000 00001111 */

int result = n1^n2; /* 00000000 00000000 00000000 00011110 */

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

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

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

return0;

}


n1 = 17

n2 = 14

result = 30

예제를 통해 XOR 연산을 확인 할수 있습니다.

다음으로 이동연산자 << 와 >> 에대해서 알아보겠습니다. 먼저 << (좌측이동) 연산자에 대해서 알아보겠습니다. << 연산자는 다른 연산자와 마찬가지로 두개의 연산자를 필요로 하며, 피연산자는 모두 정수여야 합니다. 이연산자는 다음과 같은 형식으로 사용합니다.

int C = A<<B ;

이것은 "A의 비트열을 B의 크기만큼 좌측이동시켜 C에 저장하라 !" 라는 의미입니다. 예제를 통해 알아보겠습니다.

#include <stdio.h>

int main(void)

{

int n=1;      /* 00000000 00000000 00000000 00000001 */

int r1=n<<1; /* 00000000 00000000 00000000 00000010 */

int r2=n<<2; /* 00000000 00000000 00000000 00000100 */

int r3=n<<3; /* 00000000 00000000 00000000 00001000 */

int r4=n<<4; /* 00000000 00000000 00000000 00010000 */

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

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

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

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

return 0;

}


r1 = 2

r2 = 4

r3 = 8

r4 = 16

위의 결과를 보면 알수있듯이 n<<3 은 우측으로 3칸이동시키고 빈티드를 0으로 채웁니다. 결과로 보면  을 곱한것과 같습니다. 

다음으로 우측이동 >> 에대해서 알아보도록 하겠습니다. 이연산자도 int C = A >> B; 와 같이 구성되며 "A의 비트열을 B 크기만큼오른쪽으로 이동하라 " 라는 의미가 됩니다. 예제를 통해서 알아보겠습니다.

#include <stdio.h>

int main(void)

{

int n=16;     /* 00000000 00000000 00000000 00010000 */

int r1=n>>1; /* 00000000 00000000 00000000 00001000 */

int r2=n>>2; /* 00000000 00000000 00000000 00000100 */

int r3=n>>3; /* 00000000 00000000 00000000 00000010 */

int r4=n>>4; /* 00000000 00000000 00000000 00000001 */

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

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

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

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

return 0;

}


r1 = 8

r2 = 4

r3 = 2

r4 = 1

>> 연산자는 한칸 이동함으로써 2로나누는 효과를 얻는 사실에 주목해야 합니다. 

마지막으로 단일 연산자 ~ 에 대해서 알아보도록 하겠습니다. 이연산자는 1을0으로 0을1로 반환합니다. 예제를 통해서 알아보겠습니다.

#include <stdio.h>

int main(void)

{

int n1 = -1 /* 11111111 11111111 11111111 11111111 */

int n2 = 0  /* 00000000 00000000 00000000 00000000 */

int result1 = ~n1; /* 00000000 00000000 00000000 00000000 */

int result2 = ~n2; /* 11111111 11111111 11111111 11111111 */

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

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

return 0;

}

위 예제를 통해알수 있는 내용을 정리하면 다음과 같습니다.

  • 가장왼쪽에 있는 부호 비트로 반전시킨다.

  • 피연산자가 양수일시 음수를 반환한다.

  • 피연산자가 음수일시 양수나 0을 반환한다.

이러한 비트연산자는 설정한 정보가 많은 상황에서 비트연산자를 활용한 비트마스크로 사용됩니다.


지정 연산자와 수식

수식의 예를 통해서 지정연산자를 알아보겠습니다. 다음수식을 보겠습니다.

i = i + 2

이 수식의 우변의 변수는 좌축에 중복사용됩니다. 이를 다음과같이 사용할수 있습니다.

i += 2

여기서 사용되는 += 는 지정연산자라 부릅니다. 대부분의 이원연산자 (좌측과 우측에 오퍼랜드를 갖는연산자)에는 그것에 해당하는 지정연산자가 있습니다. 지정연산자 다음중 하나가 됩니다.

+  -  *  /  %  <<  >>  &  ^  |

만약 expr1 op = expr2 라는 수식이 있다면 이수식은 expr1 = (expr1) op (expr2) 와 같습니다. 예를 들면 다음과 같습니다.

x *= y+1  이 수식은 다음수식과 같습니다.  x = (x) * (y+1)


조건문

일단 다음문장을 보도록 하겠습니다. 
if (a>b)
z = a;
else
z = b;

이문장은 a,b를 비교해 z에 큰값을 저장합니다. 이를 삼항연산자(ternary operator) "?:" 를 통해서 표현할수 있습니다. 삼원연산자는 다음과 같은 형태로 쓰여집니다.

expr1 ? expr2 : expr3;

위수식의 의미는 다음과 같습니다. 

"expr1 이 참이면 expr2 의 값이 계산되고 그렇지 않으면 expr3 의 값이 계산되고 그값이 조건문이 된다. "

위의 문장을 삼항연산자로 표현하면 다음과 같습니다.

z = (a>b) ? a:b;

삼항연산자로 표현된 다른 문장을 보겠습니다.

x= (y>0) ? fct1(5) : fct2(7);

이문장의 의미는 다음과 같습니다. 

" y가 0보다 크면 fct1 함수, 크지 않으면 fct2 함수호출, 반환값은 x 에저장"

이 삼항연산자는 잘사용하지는 않지만 적절히 사용한다면 if-else 문을 쓰는것보다 훨씬 좋은 방법이될수 있습니다.


우선순위와 계산순서

연산식안에 여러가지의 수식이 있을때 계산순서를 결정하는것이 우선순위와 결합방향입니다. 이부분에서는 우선순위와 결합방향에 대해서 알아봅니다. 간단한 수식으로 결합방향과 우선순위에 대해서 알아보도록 하겠습니다. 

위의수식의 계산과정은 다음과 같습니다.

  1. 5 - 1 - 6
  2. 4 - 6
초등학교수학에서 나올법한 식으로 알아본 우선순위는 다음과 같습니다.

  • 덧셈,뺄샘보다 곱셈을 먼저한다.

  • 연산은 왼쪽에서 오른쪽으로 순서대로 한다.

이제 우선순위와 결합방향이 무엇인지 알았으니 각연산자들의 우선순위와 결합 방향을 알아보겠습니다.
-연산자 우선순위는 다음위키백과를 참조해주시기 바랍니다. (링크)

만약 if ((x&MASK) == 0) 이라는 문장이 있으면 원하는 겂을 얻기위해서는 괄호를 반드시 써야합니다. 만약괄호를 제거 한다면 우선순위에 의해 원하는 겂을 얻을수 없습니다. 또 x = f() + g() ; 와 같은 수식은 f가 먼저 계산될수도 있고 아닐수도 있다. 그래서 f나 g가 변수를 변화시키는 경우 계산 순서에 따라 x값이 달라질수있다. 이외에 함수에서의 계산순서도 주의 해야한다. 다음문장 

printf("%d%d\n", ++n, power(2,n));

에서 ++n 의 증가시점이 컴파일러마다 다를수 있으므로 다음과 같이 쓰는것이 좋다.

++n;

printf("%d%d\n", n, power(2,n));

앞에서 살펴본듯이 약간의 차이로 계산의 결과가 달라질수있다. 따라서 괄호를 잘활용하고, 우선순위를 잘활용해야 한다.

마치며

글의 분량이 많아지면서 글의흐름이 너무 엉켜버렸네요. 글의 부족한부분이나 이해하기 어려운 부분이 있다면 질문해주시기 바랍니다. 질문을 해주시면 최선을 다해서 답변해드리겠습니다. 다음에는 C언어의 제어흐름에 대해서 알아보겠습니다. 글을읽어 주셔서 감사합니다.



'C PROGRAMMING - 기초' 카테고리의 다른 글

C언어 - 제어흐름  (0) 2012.09.23
C언어 - 자료형(Data Type)과 변수,연산자,수식 그리고 상수  (1) 2012.08.25
C언어 - 외부변수  (0) 2012.06.07
C언어 - 문자 배열  (0) 2012.05.26
C언어 - 매개변수값 전달  (0) 2012.04.22
C언어 - 함수  (0) 2012.04.21

Posted by STIH

댓글을 달아 주세요