| 연산자 종류 | 연산자 |
|---|
| 산술 연산자 | + - * / % |
| 부호 연산자 | + - |
| 대입 연산자 | = 복합 대입 연산자(+=, -=, *=, /= , %=, [비트연산자도 가능 <<= >>= &= |= ^=]) |
| 관계 연산자 | -- != <= < >= > |
| 증감 연산자 | ++ -- |
| 포인터 연산자 | * & [] |
| 구조체 연산자 | . -> |
| 논리 연산자 | || && ! |
| 비트 연산자 | | & ~ >> << |
| 삼항 조건 연산자 | ? : |
| 쉼표 연산자 | , |
| sizeof 연산자 | sizeof(타입 또는 변수) |
| 캐스트 연산자 | (type) type() |
| 괄호 연산자 | () |
1. 산술 연산자
- 나눗셈 연산자 주의 사항
- 이 연산자는 피연산자 타입에 따라 연산의 결과가 달라지는 특징이 있다.
- 피연산자에 실수형이 있으면 연산의 결과가 실수형이다.
- 정수형의 나눗셈의 경우 몫만 결과값으로 나온다.
- 나머지 연산자는 피연산자로 정수만 취할 수 있다. (결과값도 정수형이다.)
6/3
3.0/2.0
3.0/2
3/2.
3/2
2. 대입 연산자
- 대입 연산자의 우변에는 '상수, 변수와 연산자들로 구성된 계산할 수 있는 표현식'이 오며 '함수 호출문'도 올 수 있다.
- 하나의 결과를 계산해 낼 수만 있다면 어떤 표현식이 와도 상관없다.
- 대입 연산자의 좌변에는 '좌변값'만 올 수 있다.
- 실제적인 메모리를 점유하고 있고 그 값을 바꿀 수 있는 대상을 의미한다.
char str[12]; str='STRING'; 과 같은 예는 실수하기 좋은 틀린 예다.
- 문자 배열은 문자열을 저장할 수 있지만 이런 식으로 문자열을 대입할 수 없다.
왜냐하면 배열의 이름인 str은 좌변값이 아니기 때문이다.
- 배열 요소는 좌변값이지만 배열은 좌변값이 아니다.
- 다차원 배열의 경우에도 최종 요소만 좌변값이며, 다차원 배열의 부분 배열은 요소이기는 하지만 좌변값은 아니다.
- 포인터변수 ptr이 있을 때 *ptr은 좌변값이지만 &ptr은 좌변값이 아니다.
a=b=c=5 같은 코드도 사용 가능하다. c에 5가 대입되고 c변수의 값은 b에 대입된다. b변수가의 값은 a에 대입된다.
3. 증감 연산자
- 전위형 : 증감연산자가 피연산자 앞에 위치.
++a, --a
- 후위형 : 증감연산자가 피연산자 뒤에 위치.
a++, a--
int i, j;
i=j=3;
printf("%d %d\n", ++i, j++);
printf("%d %d\n", i, j);
- 참고
- c언어는 함수의 인수를 뒤에서 부터 순서대로 전달하기 때문에
int i=3; printf("%d, %d\n", i, ++i);와 같은 코드의 결과는 4 4 다.
4. 논리 연산자
- 좌변과 우변의 데이터 타입이 일치해야 한다.
- 관계 연산자는 수식을 평가하여 그 결과가 참이면 1(true)을 리턴하고 거짓이면 0(false)을 리턴한다.
- c언어에서는 0값은 항상 false 이므로 다음과 같이 활용할 수도 잇다.
if(c=a%b) 명령; 는 if(c != 0) 명령; 과 동일하다.
while(a--) 명령; 는 while(a!=0) {a--;명령;} 과 동일하다.
- 쇼트서킷(Short Circuit) 참고.
5. 비트 연산자
| 연산자 | 설명 |
|---|
| ~ | 비트를 반전시킨다. |
| & | 대응되는 비트가 모두 1일 때 1이다. |
| | | 대응되는 비트가 모두 0일 때 0이다. |
| ^ | 두 개의 비트가 달라야 1이다. (xor 연산) |
| << | 지정한 수만큼 왼쪽으로 비트들을 이동시킨다. |
| >> | 지정한 수만큼 오른쪽으로 비트들을 이동시킨다. |
- 쉬프트 연산의 피연산자는 주로 부호없는 정수형이다. 실수형은 당연히 안된다.
- 쉬프트 연산은 곱셈과 나눗셈의 대용으로 사용할 수 있다. (설명 생략)
- 회전 (Rotate)연산은 비트를 원형으로 이동시킨다.
비트 이동에 의해 밀려나는 비트는 버려지지 않고 반대쪽으로도 다시 이동된다는 것이 특징이다.
연산자 형태로는 제공되지 않으며 _rotl, _rotr 함수로 제공된다.
6. 삼항 조건 연산자
- (조건식) ? 값1:값2
- 값1 과 값2는 동일한 타입이어야 한다.
int i=3, j=4, k;
k=(i>j) ? i : j;
7. 쉼표 연산자
- 피연산자로 양쪽에 두 개의 표현식을 취하면 좌변을 먼저 평가하고 우변을 평가한 후 우변의 연산 결과를 리턴한다.
int i, j;
j=(i=3, i-2);
for (i=1, j=1; i<5; i++, j+=2){
}
8. sizeof 연산자
- 피연산자로 주어진 타입 또는 변수의 크기를 계산한다.
int i;
printf("%ld\n", sizeof(int));
printf("%ld\n", sizeof(double));
printf("%ld\n", sizeof(i));
printf("%ld\n", sizeof("string"));
int j [10][2];
printf("%ld\n", sizeof(j));
- 코드상에서 예를 들어 배열의 크기가 바뀔 우려가 있다면 배열의 크기를 받는 함수 파라미터나 피연산자를 sizeof로 사용하면 좋을 것이다.
printf("%ld\n", sizeof(j[0])/sizeof(j[0][0]));
printf("%ld\n", sizeof(j)/sizeof(j[0]));
9. 캐스트 연산자
- 캐스트 연산자는 수식내에서 변수의 타입을 강제로 다른 타입으로 바꾼다.
- c에서 지원 하는 캐스팅 연산자 : (타입)변수
- c++에서 지원하는 캐스팅 연산자 타입(변수)
- 정수와 정수의 나눗셈에 발생하는 소수점을 잃지 않기 위해서 아래와 같이 캐스팅하여 계산할 수 있다.
int i=3, j=4;
double r;
r= (double)i/j;
10. 연산 규칙
| 순위 | 연산자 | 결합순서 |
|---|
| 1 | () [] -> . | 왼쪽 우선 |
| 2 | ! ~ ++ -- + -(부호) *(포인터) & sizeof 캐스트 | 오른쪽 우선 |
| 3 | *(곱셈) / % | 왼쪽 우선 |
| 4 | + - (덧셈, 뺄셈) | 왼쪽 우선 |
| 5 | << >> | 왼쪽 우선 |
| 6 | < <= > >= | 왼쪽 우선 |
| 7 | == != | 왼쪽 우선 |
| 8 | & | 왼쪽 우선 |
| 9 | ^ | 왼쪽 우선 |
| 10 | | | 왼쪽 우선 |
| 11 | && | 왼쪽 우선 |
| 12 | || | 왼쪽 우선 |
| 13 | ? : | 오른쪽 우선 |
| 14 | = 복합 대입 | 오른쪽 우선 |
| 15 | , | 왼쪽 우선 |
- 산술 변환
- 이항 연산시 양변의 타입이 다르면 큰 쪽으로 상승 변환된다.
- 대입 연산시 좌변의 타입을 따른다.
- 함수 호출시 실인수와 형식인수의 타입이 다르면 형식인수의 타입을 따라간다.
- 형식 인수는 함수의 정의를 할 때 정의한 값을 전달 받는 변수를, 실인수는 이 변수에 대입되는 값을 의미.
- 캐스트 연산자를 사용하면 강제로 타입을 변환할 수 있다.
- 수식 내에서 사용될 경우 char, unsigned char, enum형은 int형으로 자동 확장되며, float형은 double형으로 확장된다.
- 부호 확장의 경우, 양수의 경우 1바이트 값을 2바이트로 확장할 때 16진수로 계산할 때 앞 쪽 공간에 0을 추가한다.
음수의 경우에는 f를 추가하여 확장되더라도 부호를 보존할 수 있도록한다.
출처 : 혼자 연구하는 C/C++ 1 / 김상형 저 / 와우북스