 대입문도 사실은 수식이다
 대입연산자의 변형
 증감연산자
 조건연산자
 괄호도 연산자인가?
 우선순위와 결합 순서 정리
6.1  
대입문도 사실은 수식이다
대입문
 변수에 값을 대입시키는 문장
a = a + 1;
• "a와 a+1이 같다"는 뜻이 아니라
• "a+1 값을 변수 a에 저장하라"는 뜻
 대입문 동작 과정
• 대입문 수행 전에 변수 a에 20이 저장되어 있었다면
대입 수식
 대입연산자 =
• 대입연산자(assignment operator) =도 엄연한 연산자이므로 값을 돌려준다.
• 대입연산의 결과 값은 해당 변수에 저장된 값이다.
 연속 대입
• 대입연산 결과를 이용하면 연속 대입(cascading assignment) 연산을 수행할 수 있다.

assignment.c
6.2  대입연산자의 변형
누적대입 연산자
 누적대입 연산자 형태
변수 ◎= 수식
• 여기서 ◎는 이항연산자이며
• 위 수식의 의미는 다음 수식과 같은 의미임
변수 = 변수 ◎ (수식)
 누적대입 연산자가 꼭 필요한가?
• 꼭 필요하지는 않음… 그럼 왜? 간결하기 때문
• '변수'에 해당하는 좌변이 복잡할 경우 유리함
yyval[yypv[p3+p4]+yypv[p1+p2]] += 2;
 누적대입 연산자의 ◎로 사용할 수 없는 연산자
• 크기 비교 연산자 <와 >
• 왜 그럴까요?
assignment2.c
6.3  증감연산자
증감연산자
 증가연산자
• 피연산자의 값을 하나 증가시킴
• a++; 는 a += 1;과 같은 의미
 감소연산자
• 피연산자의 값을 하나 감소시킴
• a--; 는 a -= 1;과 같은 의미
 전치와 후치
• 증감연산자는 전치, 후치에 따라 돌려주는 값이 달라진다.
• 후치일 경우(a++ 혹은 a--)에는 증감 이전 변수 값이 돌려주는 값이다.
• 전치일 경우(++a 혹은 --a)에는 증감 이후 변수 값이 돌려주는 값이다.
증가연산자 전치와 후치 비교
 초기 a, b 값이 5일 때, 후치와 전치 비교
 후치




 전치
incr.c
김소연산자 전치와 후치 비교
 초기 a, b 값이 5일 때, 후치와 전치 비교
 후치




 전치
decr.c
증감연산자에 관한 조언
 증감연산자 사용 이유
• 증감연산자를 사용하는 단 하나의 목적은 "간결하기 때문"
• 간결성 때문에 정확성을 무너뜨린다면 어리석은 짓
 증감연산자에 관한 조언
• 하나의 수식에 여러 번 사용되는 변수에는 증감연산자를 사용하지 말라
 오용 예: a에 5가 저장되어 있을 때 다음 수식의 값은?
++ a * a ++
6.4  조건연산자
조건연산자
 유일한 3항 연산자
• 형식: 조건 ? 수식1 : 수식 2
• 의미: '조건'이 참이면 '수식1' 값을, 거짓이면 '수식2' 값을 돌려줌
 사용 예
max = a > b ? a : b;
• a > b이면 max = a;
• 그렇지 않으면 max = b;
 조언
• 조건을 괄호로 감싸면 
더 이해하기 쉬움
max = (a > b)? a: b;
조건연산자에서 단락회로 계산
 단락회로 계산
• 조건연산자의 피연산자는 필요할 때만 계산된다.
• 이를 단락회로 계산(short-circuit evaluation; 지름길 계산)이라고 한다.
 단락회로 계산 예
(n != 0) sum / n: 1
• 위 수식에서 조건연산자의 피연산자는 다음 세 가지
 n != 0
 sum / n
 1
• n이 0이면 sum / n은 계산되지 않으므로 오류가 아님
• (n != 0) 1: sum / n으로 작성했다면 '0으로 나눔' 오류
조건연산자의 조건
 결과 값 수식 자료형 일치
• a ? b: c에서 b와 c의 자료형이 같아야 함
• 자료형이 다를 경우 자동 형 변환이 수행됨
 자료형 불일치 예
c ? 1: 3.14;
• 결과 값은 1 또는 3.14 중 하나임
• 1은 int형, 3.14는 double형이므로 자료형이 일치하지 않는다.
• int형 1을 double형 1.0으로 형증진(type promotion) 수행
• 따라서 c가 참일 경우의 값은 int형 1이 아니라 double형 1.0이다.
6.5  괄호도 연산자인가?
괄호도 연산자인가?
 연산자가 아닌 괄호 ( )
• 연산자 피연산자의 관계를 나타내기 위한 괄호는 연산자가 아님
(n != 0)? sum / n: 1
• 괄호로 묶은 수식을 가장 먼저 계산한다? … 꼭 그런 것은 아님
n != 0? (sum / n): 1
 연산자로 사용되는 괄호 ( )
• 함수 호출 연산에 사용된 괄호
printf("%d", n);
• 형변환 연산에 사용된 괄호
avr = sum / (double) n;
avr = sum / ((double) n);
6.6  
우선순위와 결합순서 정리
우선순위와 결합순서 정리
우선순위와 결합순서 기억 요령
 일반 법칙
• 곱은 합보다 우선한다.
• 단항연산자와 대입연산자의 결합순서는 우측에서 좌측이다.
 최고 우선순위와 최저 우선순위는 기억하자
• 최고 우선순위: () [] -> .
• 최저 우선순위: 콤마 연산자 ,
 나머지는 "계산하여 비교한 뒤, 판단하여 저장한다"
계산순서에 관한 주의사항
 우선순위/결합순서와 계산 순서는 다르다
• 우선순위/결합방향은 먼저 계산한다는 의미가 아님
• 괄호로 묶었다고 해서 먼저 계산된다는 의미도 아님
 피연산자의 계산 순서는 정의되지 않은 경우가 많음
• 예외: 단락회로 계산 연산자 && || ?: ,
• +의 계산 순서
x = f() + g();
 f가 먼저 호출된다는 보장이 없음
• 함수 인수 계산 순서 
printf("%d %d\n", ++n, power(2, n));
 ++n이 먼저 수행된다는 보장이 없음
여러 의미로 사용되는 연산 기호
 +, -, *, & 등은 단항일 때, 이항일 때 의미가 다름
Key Point
Key Point 1
 연산자의 부수효과란 연산자가 값을 돌려주는 것 외에 부수적으로 발생시키는 효과다. 
 대입 연산자는 변수에 값을 저장하는 부수효과를 발생시킬 뿐만 아니라 변수에 저장된 값을 돌려준다. 
 누적대입 연산자 ◎=(여기서 ◎는 이항 연산자)를 이용한 수식 a ◎= b는 a = a ◎ (b)와 같은 의미다. 
 누적대입 연산자는 좌변이 매우 복잡할 경우에 특히 유용하다. 
 증감 연산자는 변수의 값을 1만큼 증가시키거나 감소시킬 때 사용한다. 변수 a의 값을 1 증가시키려면 a++나 ++a를 사용하고 1 감소시키려면 a--나 --a를 사용한다. 
 증감 연산자는 전치로 사용했을 경우와 후치로 사용했을 경우에 결과 값이 다르다. 전치로 사용하면 증감된 후의 값이 결과 값이 되며 후치로 사용하면 증감되기 전의 값이 결과 값이 된다. 
Key Point 2
 조건 연산자 ?:는 피연산자를 세 개 받는 삼항 연산자이다. 조건 연산자를 사용한 수식 a?b:c의 값은 a가 참(a≠0)일 때 b가 되고 a가 거짓(a=0)일 때 c가 된다.
 조건 연산자도 단락회로 계산을 이용한다. 즉 조건 연산자의 두 번째 피연산자와 세 번째 피연산자 중 하나는 계산되지 않는다. 
 연산자의 적용 범위를 명시하기 위한 괄호는 연산자가 아니다. 괄호가 연산자로 사용되는 경우는 형 변환 연산자나 함수호출 연산자의 경우뿐이다. 
 함수호출 연산자와 멤버 추출 연산자([], ., ->)가 가장 우선순위가 높다. 나머지 연산자 중에서는 단항 연산자가 이항 연산자보다 우선순위가 높다. 같은 부류의 이항 연산자들 사이에서는 곱에 해당하는 연산(*, /, &, &&)이 합에 해당하는 연산(+, -, ^, |, ||)보다 우선순위가 높다.
 C 연산자 중에서 단항 연산자는 모두 우측에서 좌측으로 결합(우측 결합)한다. 이항 연산자들 중에서 우측 결합인 연산자는 대입 연산자(누적대입 연산자 포함) 뿐이다. 삼항 연산자인 ?:도 우측 결합이다. 나머지 연산자들은 모두 좌측에서 우측으로 결합(좌측 결합)한다.
요약(1/2)
 부수효과
• 값을 돌려주는 것 외에 부수적으로 다른 것을 변경시키는 효과
• 대입연산자, 증감연산자들은 부수효과를 발생시킨다.
 대입연산자
• 변수에 값을 대입함
• 변수에 값을 저장함
 누적대입 연산자
• (a = a ◎ (식))인 특수한 경우에는
• (a ◎= 식)으로 사용할 수 있음
 증감연산자 ++, --
• 변수의 값을 1 증가시키거나(증가연산), 1 감소시킴(감소연산)
• 전치, 후치 여부에 따라 돌려주는 값이 다름
요약(2/2)
 조건연산자 ?:
• C의 유일한 3항연산자
• 조건의 참, 거짓에 따라 돌려주는 값이 다름
• 단락회로 계산을 수행함
 괄호를 포함하는 연산자
• 함수호출, 형변환 연산자의 경우에만 괄호가 연산자로 사용됨
• 다른 경우에는 구두점(punctuation symbol)
 우선순위와 결합순서
• "계산하여 비교한 뒤, 판단하여 저장한다"
• 단항, 대입, 조건 연산자는 우측에서 좌측으로 결합
 계산순서 주의사항
• 괄호, 우선순위, 결합순서 등은 연산자와 피연산자의 관계를 명시할 뿐, 계산순서를 명시하는 것은 아님(&&, ||, ?:는 예외)
프로그래밍 실습
▶ 프로그래밍 실습 1 
 체질량지수(BMI: body mass index)를 계산하여 이에 따라 비만 여부를 판별하는 프로그램을 작성하라. 체질량지수는 다음 공식(단위: kg, cm)에 의해 계산한다.


몸무게와 키를 입력으로 받아 BMI를 출력하고 비만도를 판정하는 프로그램을 작성하라. 
▶ 프로그래밍 실습 2
 근의 공식에 따라 이차방정식의 두 근의 근사값을 구하는 프로그램을 작성하라. 이차방정식  ax2+bx+c = 0을 입력받기 위해 이차방정식의 계수 a, b, c를 입력 받는다. 이차방정식의 계수는 float 타입으로 주어지며 a는 0이 아니라고 가정한다. 이차방정식의 근의 공식은 다음 식으로 주어진다.



 근의 공식에서 제곱근을 구하기 위해서는 라이브러리 함수 sqrt를 이용하라. 예를 들어, 2의 제곱근은 sqrt(2.0)으로 구할 수 있다. 라이브러리 함수 sqrt를 사용하기 위해서는 헤더파일 <math.h>를 #include해야 한다. 
 실근이 하나인 경우에는 하나만 출력하고 실근이 두 개인 경우에는 두 근 중 작은 근을 먼저 출력해야 하며 실근이 없는 경우에는 ‘근이 없음’이라고 출력해야 한다. 







Posted by MSNU