2.8 Increment and Decrement Operators
++n
은 해당 라인이 동작하기 전에, n++
는 해당 라인이 동작한 후에 작동한다.
(i + j)++
과 같은 코드는 illegal하다. 오직 하나의 variable에 대해서만 성립하는 연산자이다.
증감연산자를 통해 코드를 간결하게 만들 수 있다.
아래는 string에서 문자하나를 모두 없애는 함수이다.
void squeeze(char s[], int c){
int i,m j;
for(i = j = 0; s[i] != '\0'; i++)
if(s[i] != c)
s[j++] = s[i]; // j++; 안해도 된다.
s[j] = '\0';
}
strcat()이라는 두 string을 연결하는 함수를 예로 들면 아래와 같이 조건문을 실행문으로 사용함과 동시에 간결하게 작성할 수 있다.
void strcat(char s[], char t[]){
int i, j;
i = j = 0;
while(s[i] != '\0')
i++;
// s에 t의 원소를 넣고, \0과 비교한 뒤, 각 원소의 인덱스를 1 증가
while((s[i++] = t[j++]) != '\0')
;
}
2.9 Bitwise Operators
비트 연산자는 signed, unsigned에 관계없이 정수자료형(char, short, int, long)에만 적용된다.
& and 연산
| or 연산
^ xor 연산
<< 왼쪽 비트 이동
>> 오른쪽 비트 이동
~ 1의 보수 연산
&연산은 비트를 mask off할때 사용한다.
예를 들어 n = n & 0177;
은 n = n & B001111111;
이므로, 하위 7비트를 제외한 모든 비트를 0이 되게한다. 하위 7비트는 그대로 유지된다.
|연산은 비트를 on할때 사용한다.x = x | 1<<3
하면 우측에서 3번째 비트가 1이 된다. 나머지 비트는 유지된다.
^연산은 두 operand의 비트가 같으면 0이 나오게하고, 다르면 1이 나오게한다.
<<연산은 operand의 비트가 왼쪽으로 이동하도록 한다.x << 2
는 x의 비트를 2칸 이동시키고, 남은 부분은 0으로 채우는 연산이다. 이는 4를 곱한 것과 같다.
>>연산은 unsigned는 남는 비트를 다 0으로 채운다. signed의 경우, 기계에 따라서 남는 비트에 signed비트를 넣거나(이 경우를 arithmetic shift라고한다.), 0비트를 넣거나(이 경우를 logical shift)로 나뉜다.
~연산은 1의보수를 구하는 연산으로, 1비트는 0비트로, 0비트는 1비트로 바꾼다.
예를들면 x = x & ~077
은 x = x & ~(00111111)
이고, x = x & 11000000
이다.x = x & ~077
같은 표현은 컴파일시에 연산이 처리되기에 extra cost가 소요되지는 않는다.
이를 종합해서 새로운 함수를 만들자
아래는 p에서 시작하는 n개의 비트필드를 만드는 함수이다.getbits(x, 4, 3)
은 우측을 기준으로한 offset으로 4,3,2번째 비트를 우측에 정렬된 상태로 반환한다.
unsigned getbits(unsigned x, int p, int n){
return (x >> (p + 1 -n)) & ~(~0 << n);
}
사용예를 보여주자면
getbits(1010 1010, 5, 3)
0001 0101 // (x >> (p + 1 -n)) 결과
0000 0111 // ~(~0 << n) 결과
0000 0101 // 최종결과
주의!!!
&, |(비트연산자)와 &&, ||(논리 연산자)은 다른 연산자이다.