[C 언어의 기초]연산자 2부






기타 연산자 - 1




1. modulus 연산자 : % 

%는 나머지를 구하는 연산으로 5%3은 5÷3의 나머지가 구해져 답은 2이다. % 연산자는 정수형의 연산에만 사용한다. 간단하게 말하자면, 정수 나눗셈에서 나머지 값을 구하는 연산이다.


확인 문제 1.

/* 제산 연산자('/')를 사용한 연산의 결과 확인 */

#include<stdio.h>

main()

{

int a;

double df;

printf("%d\n", 8 / 5); /* 정수형피연산자 */

printf("%lf\n", df = 8 / 5); /* 정수형 피연산자 */

printf("%lf\n", 8.0 / 5.0); /* 부동형 피연산자 */

printf("%lf\n", 8.0 / 5); /* 부동형과 정수형 피연산자 */

printf("%lf\n", 8 / 5.0); /* 정수형과 부동형 피연산자 */

printf("%d\n", a=8.0 / 5.0); /* 부동형 피연산자 */

printf("%d\n", 8.0 / 5.0); /* 부동형 피연산자를 %d로출력 */

}


예제 1.

#include <stdio.h>

#define SM 60/* 1분은 60*/

 

main()

{

int sec, min, left;

printf("Input seconds = ");

scanf("%d", &sec); /* '&' 기호를 빠트리면 큰일 난다 */

min = sec / SM;

left = sec % SM;

printf("%d seconds = %d minute %d sec.\n", sec, min, left);

 

}



예제 프로그램 1는 / 연산자와 와 % 연산자를 초를 분과 초로 변환하는 프로그램이다. 예를 들어 125초라면 2분 5초로 계산하는 프로그램이다. / 연산자를 이용하여 계산하는 몫은 분으로% 연산자를 이용하여 계산한 나머지는 초로 계산된다. 단지 주의할 함수는 printf() 함수가 표준 출력 장치인 터미널로 출력하는 함수인 것처럼,scanf() 함수는 표준 입력 함수인 키보드를 통해 필요한 데이터를 입력해야 한다.


/* 모듈로('%') 연산자의 사용 :centimeter를 meter로 환산하는 프로그램 */

#include<stdio.h>

#define CM_PER_M 100

main()

{

int meter, remainder;

long centimeter;

printf("Convert cetimeters to centimeters and meters!!\n");

printf("Enter the number of cetimeters you wish to convert:");

while(scanf("%ld", &centimeter) == 1)

{

meter = centimeter / CM_PER_M;

remainder = centimeter % CM_PER_M;

printf("%ld centimeter is %d.%d meters\n\n",

centimeter, meter, remainder);

printf("Enter the number of cetimeters you wish to convert:");

}

}




2. 증감 연산자 : ++, --

C 언어를 대표하는 연산자에는 증/감 연산자가 있다. ++ 를 증가 연산자, --를 감소 연산자라고 한다. 아래의 설명문에 있는 대로 각각 변수의 값을 하나씩 증가 혹은 감소시키는 연산자이다.

i++; ++i; /* i = i + 1; */

i--; --i; /* i =i - 1; */

예제 2.

#include <stdio.h>

 

main()/* 120까지 제곱을 계산하여 역순으로 출력 */

{

int n = 20;

while (n > 0) {

printf(" %10d : %10d\n", n, n*n);

n = n - 1; /* n--; 또는 --n; */

}

}



예제 프로그램 2에서 n=n-1;은 설명문에 있는 대로 n--; 혹은 --n;과 같은 의미로 서로 바꿔서 표현해도 된다.



예제 3


#include <stdio.h>

main()

{

int a = 1, b = 1;

int aplus, plusb;

aplus = a++;

plusb = ++b;

printf("aplus = %d, plusb = %d\n", aplus, plusb);

}



예제 프로그램 3을 실행시켜 보자. 결과는 어떻게 나오는가? 자신의 예상과 비교해 보자. aplus의값은 1이고 bplus의 값은 2로 출력된다. 그 이유는 후위 증가 연산자 ++는 값이 사용되고 나서 증가되는 것이고, 전위 증가 연산자 ++는 일단 값이 증가되고 나서 사용되기 때문이다.


/* 전위 증가 연산과 후위 증가 연산의 예 */

#include<stdio.h>

main()

{

int pre_inc = 0, post_inc = 0;

int pre_result, post_result;

while( pre_inc <= 2)

{

++pre_inc;

post_inc++;

printf("pre_inc = %d, post_inc = %d\n", pre_inc, post_inc);

}

put char('\n');

pre_result = post_result = 0;

pre_inc = post_inc = 0;

while( pre_inc <= 2)

{

pre_result = ++pre_inc;

post_result = post_inc++;

printf("pre_inc = %d, post_inc = %d\n",

pre_inc, post_inc);

printf("pre_result = %d, post_result = %d\n",

pre_result, post_result);

}

}


※ 그러나 아래의 예와 같이 결과가 모호한 경우에는 증감 연산자의 사용을 피해야 한다 !!!

ans = num/2 + 5 * (1 + num++);

printf("%d, %d\n", num, num*num++);

/* 증감 연산자의 부작용 */

#include<stdio.h>

main()

{

int I, j, k;

I = j = k = 5;

printf("%d,%d\n", i, i++);

printf("%d\n", -j+ j++);

printf("%d\n", k++ + -k);

i = j = k = 5;

printf("%d\n", ++j +j);

printf("%d\n", k++ +k);

i = j = k = 5;

printf("%d\n", ++i +i +i);

printf("%d\n", j + ++ j + j);

printf("%d\n", k + k+ ++k);

}


확인 문제의 실행 결과는 컴파일러마다 차이가 있습니다. 컴파일러 마음대로 라는 이야기이지요. 터보씨의 경우 함수에 전달되는 실인수는 오른쪽에서 왼쪽으로 평가되기 때문이지요. 즉, i++가 먼저 평가되고 나서 i가 평가되므로 6과 5가 출력됩니다. 다음 2개의 식을 봅시다. 터보 씨의 경우입니다.

-i + j++

k++ + -k

먼저 변수 j, k에는 5가 저장되어 있기 때문에 위의 첫 번째 식은 (-5) + 5가 되므로 계산 결과는 0이 출력된다. 그러나 두번째 식에서 첫 번째 부분식 k++가 평가될 때 변수 k는 1만큼 증가되고, 두 번째 부분식 –k는 1만큼 증가된 (-6)이 되므로, 결국 5 + (-6)의 식을 계산하므로 -1이 됩니다.

++j +j

k + ++k

변수 j, k는 모두 5이므로 첫 번째 식에서 먼저 선행 증가 연산자 ++에 의해서 j가 1만큼 증가되고, 다시 j가더해지므로 6 + 6이 되어 12를 출력할 것입니다. 그러나 두 번째 식에서 5 + 6이 되어 11이 출력될 것이라고 생각하기 쉬운데, 그 결과는 12가 됩니다.

즉, 덧셈연산자 우측의 피연산자가 먼저 평가되어 6으로 증가한 다음에 덧셈 연산자의 좌측에 있는 피연산자를 평가합니다. 결국 6 + 6이 되어 12가 최종 결과가 됩니다. 

어떻게 된 것일까요? 참으로 이해할 수 없는 문제입니다. 결론적으로 하나의 식에 동일한 변수가 두 번 이상 나타날 경우 컴파일러는 식을 평가할 때 어떤 원칙을 정해 놓고 평가하는 것이 아니라 식에 따라 컴파일러 편의대로 평가를 달리한다는 것입니다. 마지막 출력문에 있는 식을 봅시다.

k + k + ++k

위의 식은 연산자의 우선 순위에 따라 다음과 같이 연산을 한다고 생각할 수 있습니다.

(k + k + (++k))

따라서 증가 연산자가 먼저 평가되므로 6 + 6 + 6 = 18로 생각할 수 있는데, 컴파일러는 5 + 5 + 6 = 16으로 평가합니다. 컴파일러 편의대로 식을 평가했다는 것입니다. 결론적으로 하나의식에 두 개 이상의 변수가 사용되고, 그 변수에 증감 연산자를 사용할 경우 컴파일러는 연산자의 우선순위에 의해서 식을 평가하는 것이 아니라 컴파일러 편의대로 식을 평가합니다. 따라서 이러한 문제점을 제거하려면 반드시 다음 두 개의 규칙을 준수하기 바랍니다.

① 함수 전달 인수로 동일한 변수가 한 번 이상 사용될 경우 사용된 변수에 증감 연산자를 사용하면 안 된다.

② 식에서 한 번 이상 나오는 변수에 증감 연산자를 사용하면 안 된다.

식의 평가 순서를 컴파일러에 의존하거나 의도적으로 부작용을 만드는 프로그램을 작성하지 않는 것이 좋습니다. 이러한 문제점을 해결하려면 식에 괄호를 적절히 사용하거나 임시 변수를 사용하는 것이 좋습니다. 따라서 다음 식은 임시 변수를 사용하여 다음과 같이 작성하는 것이 좋습니다.

result = k + ++k;

① 11을 얻고자 한다면, temp = k; result = temp + ++k;

② 12를 얻고자 한다면, temp = ++k; result = temp + k;


3. comma 연산자 : 놓여진 순서대로 연산하는 연산자

i = (j = 15, j + 4); ===> /* j =15; i = j + 4; 와 동일함 */





Reactions

댓글 쓰기

0 댓글