Part 06 세상을변화시키는연산자 1
이장의내용 대입문도사실은수식이다 대입연산자의변형 증감연산자 조건연산자 괄호도연산자인가? 우선순위와결합순서정리 2
6.1 대입문도사실은수식이다 3
대입문 변수에값을대입시키는문장 a = a + 1; "a 와 a+1 이같다 " 는뜻이아니라 "a+1 값을변수 a 에저장하라 " 는뜻 대입문동작과정 대입문수행전에변수 a 에 20 이저장되어있었다면 부수효과 (side effect) + 연산자나함수가값을리턴 (return) 하는것외에도 변수값을변경시키는등 부수적으로발생시키는효과 = 4
대입수식 대입연산자 = 대입연산자 (assignment operator) = 도엄연한연산자이므로값을돌려준다. 대입연산의결과값은해당변수에저장된값이다. 연속대입 대입연산결과를이용하면연속대입 (cascading assignment) 연산을수행할수있다. = b = a = 2; // b = (a = 2); 와같은의미 = 5
assignment.c 실행결과 : 초기의 a 와 b 값입니다. a = 0, b = 0 a = a + 1; 을수행했습니다. a = 1, b = 0 b = a = 2; 를수행했습니다. a = 2, b = 2 6
6.2 대입연산자의변형 7
누적대입연산자 누적대입연산자형태 C 의철학 변수 = 수식 여기서 는이항연산자이며 위수식의의미는다음수식과같은의미임변수 = 변수 ( 수식 ) 누적대입연산자가꼭필요한가? 꼭필요하지는않음 그럼왜? 간결하기때문 ' 변수 ' 에해당하는좌변이복잡할경우유리함 yyval[yypv[p3+p4]+yypv[p1+p2]] += 2; 누적대입연산자의 로사용할수없는연산자 크기비교연산자 < 와 > 왜그럴까요? C 언어의설계철학은간결성이다. 8
assignment2.c 실행결과 : 초기의 a 값입니다. a = 0 a += 1; 을수행했습니다. a = 1 a += a + 1; 을수행했습니다. a = 3 a *= a * a; 를수행했습니다. a = 27 9
6.3 증감연산자 10
증감연산자 증가연산자 피연산자의값을하나증가시킴 a++; 는 a += 1; 과같은의미 감소연산자 피연산자의값을하나감소시킴 a--; 는 a -= 1; 과같은의미 전치와후치 증감연산자는전치, 후치에따라돌려주는값이달라진다. 후치일경우 (a++ 혹은 a--) 에는증감이전변수값이돌려주는값이다. 전치일경우 (++a 혹은 --a) 에는증감이후변수값이돌려주는값이다. 11
증가연산자전치와후치비교 초기 a, b 값이 5 일때, 후치와전치비교 후치 단계 수행연산 수식 a 값 b 값 0 N/A b = 2 * a++ 5 5 1 ++ b = 2 * 5 6 5 2 * b = 10 6 5 3 = 10 6 10 전치 단계수행연산수식 a 값 b 값 0 N/A b = 2 * ++a 5 5 1 ++ b = 2 * 6 6 5 2 * b = 12 6 5 3 = 12 6 12 12
incr.c 실행결과 : 초기의 a 와 b 값입니다. a = 5, b = 5 b = 2 * a++; 를수행했습니다. a = 6, b = 10 13
김소연산자전치와후치비교 초기 a, b 값이 5 일때, 후치와전치비교 후치 단계 수행연산 수식 a 값 b 값 0 N/A b = 2 * a-- 5 5 1 -- b = 2 * 5 4 5 2 * b = 10 4 5 3 = 10 4 10 전치 단계수행연산수식 a 값 b 값 0 N/A b = 2 * --a 5 5 1 -- b = 2 * 4 4 5 2 * b = 8 4 5 3 = 8 4 8 14
decr.c 실행결과 : 초기의 a 와 b 값입니다. a = 5, b = 5 b = 2 * --a; 를수행했습니다. a = 4, b = 8 15
증감연산자에관한조언 증감연산자사용이유 증감연산자를사용하는단하나의목적은 " 간결하기때문 " 간결성때문에정확성을무너뜨린다면어리석은짓 증감연산자에관한조언 하나의수식에여러번사용되는변수에는증감연산자를사용하지말라 오용예 : a 에 5 가저장되어있을때다음수식의값은? ++ a * a ++ 16
6.4 조건연산자 17
조건연산자 유일한 3 항연산자 형식 : 조건? 수식 1 : 수식 2 의미 : ' 조건 ' 이참이면 ' 수식 1' 값을, 거짓이면 ' 수식 2' 값을돌려줌 사용예 max = a > b? a : b; a > b 이면 max = a; 그렇지않으면 max = b; 조언 조건을괄호로감싸면더이해하기쉬움 max = (a > b)? a: b; 18
조건연산자에서단락회로계산 단락회로계산 조건연산자의피연산자는필요할때만계산된다. 이를단락회로계산 (short-circuit evaluation; 지름길계산 ) 이라고한다. 단락회로계산예 (n!= 0) sum / n: 1 위수식에서조건연산자의피연산자는다음세가지 n!= 0 sum / n 1 n 이 0 이면 sum / n 은계산되지않으므로오류가아님 (n!= 0) 1: sum / n 으로작성했다면 '0 으로나눔 ' 오류 19
조건연산자의조건 결과값수식자료형일치 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 이다. 20
6.5 괄호도연산자인가? 21
괄호도연산자인가? 연산자가아닌괄호 ( ) 연산자피연산자의관계를나타내기위한괄호는연산자가아님 (n!= 0)? sum / n: 1 괄호로묶은수식을가장먼저계산한다? 꼭그런것은아님 n!= 0? (sum / n): 1 연산자로사용되는괄호 ( ) 함수호출연산에사용된괄호 printf("%d", n); 형변환연산에사용된괄호 avr = sum / (double) n; avr = sum / ((double) n); 22
6.6 우선순위와결합순서정리 23
우선순위와결합순서정리함수호출연산자 형변환연산자 24
우선순위와결합순서기억요령 일반법칙 곱은합보다우선한다. 단항연산자와대입연산자의결합순서는우측에서좌측이다. 최고우선순위와최저우선순위는기억하자 최고우선순위 : () [] ->. 최저우선순위 : 콤마연산자, 나머지는 " 계산하여비교한뒤, 판단하여저장한다 " 25
계산순서에관한주의사항 우선순위 / 결합순서와계산순서는다르다 우선순위 / 결합방향은먼저계산한다는의미가아님 괄호로묶었다고해서먼저계산된다는의미도아님 피연산자의계산순서는정의되지않은경우가많음 예외 : 단락회로계산연산자 &&?:, + 의계산순서 x = f() + g(); f 가먼저호출된다는보장이없음 함수인수계산순서 printf("%d %d\n", ++n, power(2, n)); ++n 이먼저수행된다는보장이없음 26
여러의미로사용되는연산기호 +, -, *, & 등은단항일때, 이항일때의미가다름 27
Key Point 28
Key Point 1 연산자의부수효과란연산자가값을돌려주는것외에부수적으로발생시키는효과다. 대입연산자는변수에값을저장하는부수효과를발생시킬뿐만아니라변수에저장된값을돌려준다. 누적대입연산자 =( 여기서 는이항연산자 ) 를이용한수식 a = b 는 a = a (b) 와같은의미다. 누적대입연산자는좌변이매우복잡할경우에특히유용하다. 증감연산자는변수의값을 1 만큼증가시키거나감소시킬때사용한다. 변수 a 의값을 1 증가시키려면 a++ 나 ++a 를사용하고 1 감소시키려면 a-- 나 --a 를사용한다. 증감연산자는전치로사용했을경우와후치로사용했을경우에결과값이다르다. 전치로사용하면증감된후의값이결과값이되며후치로사용하면증감되기전의값이결과값이된다. 29
Key Point 2 조건연산자?: 는피연산자를세개받는삼항연산자이다. 조건연산자를사용한수식 a?b:c 의값은 a 가참 (a 0) 일때 b 가되고 a 가거짓 (a=0) 일때 c 가된다. 조건연산자도단락회로계산을이용한다. 즉조건연산자의두번째피연산자와세번째피연산자중하나는계산되지않는다. 연산자의적용범위를명시하기위한괄호는연산자가아니다. 괄호가연산자로사용되는경우는형변환연산자나함수호출연산자의경우뿐이다. 함수호출연산자와멤버추출연산자 ([],., ->) 가가장우선순위가높다. 나머지연산자중에서는단항연산자가이항연산자보다우선순위가높다. 같은부류의이항연산자들사이에서는곱에해당하는연산 (*, /, &, &&) 이합에해당하는연산 (+, -, ^,, ) 보다우선순위가높다. C 연산자중에서단항연산자는모두우측에서좌측으로결합 ( 우측결합 ) 한다. 이항연산자들중에서우측결합인연산자는대입연산자 ( 누적대입연산자포함 ) 뿐이다. 삼항연산자인?: 도우측결합이다. 나머지연산자들은모두좌측에서우측으로결합 ( 좌측결합 ) 한다. 30
요약 (1/2) 부수효과 값을돌려주는것외에부수적으로다른것을변경시키는효과 대입연산자, 증감연산자들은부수효과를발생시킨다. 대입연산자 변수에값을대입함 변수에값을저장함 누적대입연산자 (a = a ( 식 )) 인특수한경우에는 (a = 식 ) 으로사용할수있음 증감연산자 ++, -- 변수의값을 1 증가시키거나 ( 증가연산 ), 1 감소시킴 ( 감소연산 ) 전치, 후치여부에따라돌려주는값이다름 31
요약 (2/2) 조건연산자?: C 의유일한 3 항연산자 조건의참, 거짓에따라돌려주는값이다름 단락회로계산을수행함 괄호를포함하는연산자 함수호출, 형변환연산자의경우에만괄호가연산자로사용됨 다른경우에는구두점 (punctuation symbol) 우선순위와결합순서 " 계산하여비교한뒤, 판단하여저장한다 " 단항, 대입, 조건연산자는우측에서좌측으로결합 계산순서주의사항 괄호, 우선순위, 결합순서등은연산자와피연산자의관계를명시할뿐, 계산순서를명시하는것은아님 (&&,,?: 는예외 ) 32
프로그래밍실습 33
프로그래밍실습 1 체질량지수 (BMI: body mass index) 를계산하여이에따라비만여부를판별하는프로그램을작성하라. 체질량지수는다음공식 ( 단위 : kg, cm) 에의해계산한다. 몸무게와키를입력으로받아 BMI 를출력하고비만도를판정하는프로그램을작성하라. 34
프로그래밍실습 2 근의공식에따라이차방정식의두근의근사값을구하는프로그램을작성하라. 이차방정식 ax 2 +bx+c = 0 을입력받기위해이차방정식의계수 a, b, c 를입력받는다. 이차방정식의계수는 float 타입으로주어지며 a 는 0 이아니라고가정한다. 이차방정식의근의공식은다음식으로주어진다. 근의공식에서제곱근을구하기위해서는라이브러리함수 sqrt 를이용하라. 예를들어, 2 의제곱근은 sqrt(2.0) 으로구할수있다. 라이브러리함수 sqrt 를사용하기위해서는헤더파일 <math.h> 를 #include 해야한다. 실근이하나인경우에는하나만출력하고실근이두개인경우에는두근중작은근을먼저출력해야하며실근이없는경우에는 근이없음 이라고출력해야한다. 35