int n=10;
printf("%d", n++); //출력:10
print("%d", n); //출력:11
int n=10;
printf("%d", ++n); //출력:11
print("%d", n); //출력:11
int n=10;
printf("%d", n--); //출력:10
print("%d", n); //출력:9
int n=10;
printf("%d", --n); //출력:9
print("%d", n); //출력:9
x = a++
x = ++a
잘못된 사용 예시
int a=10;
++300; //상수에는 증감연산자 사용 불가
(a+1)--; //일반 수식에는 증감연산자 사용 불가
//하나의 연산식에 동일한 변수의 증감연산자는 사용되도록이면 하지 않기
a = ++a * a--;
증가 감소 연산자
int main()
{
int m = 10, n=5;
int result;
result = m++ + --n;
printf("m=%d n=%d result=%d\n", m,n,result);
result = ++m - n--;
printf("m=%d n=%d result=%d\n", m,n,result);
return 0;
}
출력:
n=4 result=14
m=12 n=3 result=8
⇒ 논리연산자 &&와 ||는 피연산자 두 개 중에서 왼쪽 피연산자만으로 논리연산 결과가 결정된다면 오른쪽 피연산자는 평가하지 않는다. (연산의 효율을 up)
예를 들어, x&&y 연산식에서 x의 값이 0(거짓)이라면 y의 값을 평가하지 않고 x&&y 결과는 바로 0이 된다. && 연산에서는 피연산자 둘 다 참(true)이어야 하기 때문에 x가 참이면 더 볼 것도 없이 false.
예시
int main()
{
int a=10, b=5, m=1;
int result;
result = (a<b) && (m++ == 1); // a<b는 false이기 때문에 0이 결과값, m++ == 1은 참이기 때문에 1이 결과값. &&이기 때문에 0이 result에 대입.
printf("m=%d result=%d\n", m,result);
result = (a>b) || (--m==0);
printf("m=%d result=%d\n", m,result);
return 0;
}
출력값:
m=1 result=0
m=1 result=1
연산자 ? :
조건 연산자는 조건에 따라 주어진 피연산자가 결과값이 되는 삼항연산자이다.
예) 연산식 (x ? a : b)에서 피연산자는 x,a,b, 3 개이며, 첫 번째 피연산자인 x가 참이면(0이 아니면) 결과는 a이며, x가 0이면(거짓) 결과는 b이다. 즉, x에 따라 결과는 a또는 b이다.
조건연산자를 이용하면 두 수의 최대값과 최소값을 쉽게 구할 수 있다. 절대값도 쉽게 구할 수 있다.
예)
max = (a>b) ? a : b; //a가 b보다 크면 max = a
max = (a<b) ? b : a;
min = (a>b) ? b : a;
min = (a<b) ? a : b;
absolute = (a>0) ? a : -a; //절대값 반환 조건연산
absolute = (a<0) ? -a : a;
정수형에 대한 비트 중심 연산자로 비트 논리연산자와 이동연산자가 제공된다.
비트 논리 연산자
⇒ 피연산자 정수값을 비트 단위로 논리 연산을 수행하는 연산자로, &,|,^,~ 이 4 가지이다.
예) 3 & 5
3: 0011
5: 0101
3 & 5 = 1 0001
예) 3 | 4
3: 0011
4: 0100
3 | 4 = 7 0111
예) 3 ^ 4
3: 0011
4: 0100
3 ^ 4 = 7 0111
비트 이동 연산자 (bit shift operators)
⇒ >> 또는 <<는 연산자의 방향인 왼쪽이나 오른쪽으로, 비트 단위로 줄줄이 이동시키는 연산자이다.
예)
#include <stdio.h>
int main(void){
unsigned char a = 4 << 1; // 0000 0100
unsigned char b = 8 << 2; // 0000 1000
printf("4 << 1 : %d\n", a);
printf("8 << 2 : %d\n", b);
a = 6 << 3; // 0000 0110
b = 10 << 4; // 0000 1010
printf("6 << 3 : %d\n", a);
printf("10 << 4 : %d\n", b);
}
연산 설명: - a는 원래 4 (0000 0100) 이지만 << 1 을 했기 때문에 8 (0000 1000)이 된다.
- b는 원래 8 (0000 1000) 이지만 << 2 를 했기 때문에 32(0010 0000) 가 된다.
비트가 한 자리씩 왼쪽으로 이동할 때마다 정수의 값은 두 배가 된다.
2진수이기 때문에 2칸을 이동하면 4배가 되고, 3칸을 이동하면 8배가 된다. 즉, 2의 n승 만큼 곱하면 된다.
비트 연산은 비트 단위에서 직접 조작하기 때문에 일반 사칙 연산보다 더 빠르다.
추가 예시)
-16387: 0100 0000 0000 0011
16387 << 2 ⇒ 0000 0000 0000 1100 (=12)
(기존 가장 왼쪽에서 두 번째에 있던 1이 왼쪽으로 빠져버려서 없어짐)
16387 >> 2 ⇒ 0001 0000 0000 0000 (=4096)
(기존 가장 오른쪽에서 있던 1 두 개가 오른쪽으로 밀려나서 빠져버림)
signed의 경우: 부호비트(0 or 1) 값으로 채워진다.
unsigned의 경우: 0으로 채워짐.
자동 올림 변환
7 + 5.2 식에서 7이 7.0 (double)로 자동 올림 변환이 됨. ⇒ 7.0 + 5.2 = 12.2 (double) 이 된다.
다양한 올림변환의 예)
보아하니 데이터 손실이 가장 적은 방안으로 자료형이 자동으로 올림변환 되는 것 같다.
자동 내림/올림
int a = 3.4; //자동으로 내림변환되어 변수 a에는 3이 저장된다.
double d = 3; // 자동으로 올림변환되어 변수 d에는 3.0이 저장된다.
*int a = 3.4; 라는 식을 작성하게 되면 컴파일 중 아래와 같은 오류 메시지가 나올 수 있음:
Warning C4244: ~~ 'double'에서 'int'로 변환하면서 데이터가 손실될 수 있습니다.
형변환 연산자
-강제 형변환 / 데이터 손실 우려 있음
(int) 30.525 //30으로 저장
//다양한 예시:
(int) 'A' //65
(int) 3.14 //3
(double) 9 // 9.0
(double) 3.4F // 3.4
(double) 7/2 // 3.5
예)
double result = (double) 7/2;
// 7.0/2가 되어서 결과가 3.5가 되어 result에 대입됨.
// 형변환을 사용하지 않으면 7/2는 그냥 3이 되어 3.0이 result에 대입됨.
//다양한 예시:
(int) 3.8 + 5.7 // 8.7
3.8 + (int) 5.7 // 8.8
(int) 3.8 + (int) 5.7 // 8
(int) (3.8+5.7) // 9
7/2 // 3
7.0 / 2 //3.5
7 / (double) 2 // 3.5
연산자 sizeof
형식: sizeof (exp_or_keyword)
sizeof (int) //결과는 4
sizeof (3.14) // 결과는 8
sizeof a // 결과는 2 (short a;)
//비트 크기랑 연관 있나?
콤마 연산자 (,)
형식: exp1 , exp2
위 형식에서, 결과값은 나중에 계산된 exp2의 결과값이다.
콤마 연산자는 둘 이상의 변수를 동시에 선언하거나, 둘 이상의 문장을 한 행에 삽입하는 경우에 사용됨.
또한, 둘 이상의 인자를 함수로 전달할 때도 인자의 구분을 목적으로 사용되기도 함.
int main(void)
{
int num1=1, num2=2;
printf("Hello "), printf("world! \n");
num1++, num2++;
printf("%d ",num1), printf("%d ",num2), printf("\n");
return 0;
}
이렇게 둘 이상의 함수 호출문이나 연산문이 하나의 문장 안에 삽입되어 있는 것을 볼 수 있음.
3+4, 5-10 이라는 식에서는 결과는 -5
3+4, 5-10, 2*3 이라는 식에서는 결과는 6
int main()
{
int x;
printf("%d", (x=3+4,2*3));
return 0;
}
출력값: 6
//연산자 우선 순위가 작용하는 것
결합성
int n = 10, m =5;
n += m /= 3;
우에서 좌(←)로 먼저 결합하는 축약 대입연산자
m /= 3 는 곧 m = m/3 —> 결과는 1 (5 / 3 = 1)
그러면 n += 1, 즉, n = n + 1 이 최종 식이 된다.
n은 10이기 때문에 결국 최종값은 11