1. 비트연산자
1) 2진수와 16진수
- 컴퓨터의 기본 정보단위는 bit와 byte로 표현
- 2진수, 16진수 표기가 편리한 경우가 있음
- 1 bit: 2진수 한 자리
- 1 byte: 16진수 두 자리
- 2진수 4자리 == 16진수 1자리
2) 비트 연산
- 비트 단위로 처리되는 연산
- 1: 참
- 0: 거짓
- 비트 연산의 종류: 비트 단위 논리 연산, 비트 단위 이동 연산
<비트 단위 논리 연산>
(1) x & y
- x와 y 비트 단위 AND(논리곱) 연산
- 둘 다 비트가 1인 경우: 1
- 둘 중 하나라도 비트가 0인 경우: 0
(2) x : y
- x와 y 비트 단위 OR(논리합) 연산
- 둘 중 하나라도 비트가 1인 경우: 1
- 둘 다 비트가 0인 경우: 0
(3) x ^ y
- x와 y 비트 단위 XOR 연산
- 비트의 합이 홀수 or 1의 개수가 홀수 or 두 비트가 다른 경우: 1
- 비트의 합이 짝수 or 1의 개수가 짝수 or 두 비트가 같은 경우: 0
(4) ~ x
- x 에 대한 NOT 연산
- 비트가 1인 경우: 0
- 비트가 0인 경우: 1
<비트 단위 이동 연산>
(1) x << n
- x를 n비트 왼쪽 이동
- 왼쪽 n개의 비트는 삭제
- 오른쪽에 남은 공간은 0으로 채우기
(2) x>>n
- x를 n비트 오른쪽 이동
- 오른쪽 n개의 비트는 삭제
- 왼쪽에 남은 공간은 0으로 채우기
3) 비트연산의 피연산자
- 피연산자는 정수형(char, int, long 등) 에 대해서만 연산 가능
- 특별한 이유가 없으면 unsigned 정수 사용 (0과 양수)
- 이동 연산에서 빈자리는 0으로 채우는 것이 기본이지만, signed 정수는 1로 채워지는 경우도 있음
2. 재귀 함수
1) 함수 호출과 반환
- 어떠한 함수가 존재한다 가정할 때, 해당 함수를 여러번 반복하여 호출하면?
- 하나의 함수가 반복하여 여러번 요청을 처리하는 것이 아니다.
- 동일한 기능을 가진 3개의 함수가 각각의 요청을 처리하는 것이다.
- 따라서 하나의 함수의 내부에서 동일한 이름의 함수를 호출 할 수 있다.
- 일을 시행하고 있는 해당 함수가 다시 일을 처리하는 것이 아닌,
- 동일 기능의 다른 함수에게 요청하는 것이기 때문
2) 재귀 함수 동작 과정
- 하위 함수를 주어진 만큼 반복하여 호출하여,
- 최하위 함수까지 간 이후
- 최상위 함수로 차례대로 복귀한다
예시)
void circle(int x){
printf("call: x=%d\n", x);
if (x > 1) circle(x-1);
printf("return: x=%d\n", x);
}
int main(){
circle(3);
return 0;
}
>> 출력
call: x=3 // circle(3) 호출
call: x=2 // circle(2) 호출
call: x=1 // circle(1) 호출
return: x=1 // circle(1) 마무리
return: x=2 // circle(2) 마무리
return: x=3 // circle(3) 마무리
3) 재귀 함수
- 함수 내부에서 자기와 동일한 이름의 함수를 호출하는 함수
- 유사 개념: 점화식
- 주의 사항: 재귀 호출의 종료 조건이 없으면 제대로 동작하지 않음
- 점화식에서 초기항이 없으면 정의되지 않는 것과 유사
3. 라이브러리 활용
1) 난수(Random Number) 생성
- 난수: 정의된 범위 내에서 임의로 추출되는 수
- C언어에서는 난수를 생성하는 함수 제공
- ex) rand(), srand(), time()
(1) rand() 함수
- <stdlib.h>에 선언되어 있음
- 0 ~ RAND_MAX 사이의 임의의 수 리턴
- RAND_MAX는 stdlib.h에 정의된 상수 (32767)
예시)
#inlcude<stdio.h>
#include<stdlib.h>
int main(){
for (int i = 0; i<5; i++){
printf("%d", rand());
}
return 0;
}
(2) srand() 함수
- <stdlib.h>에 선언되어 있음
- rand() 함수의 시드(seed) 변경
- 시드(seed) 값이 동일하면, 특정 회차의 rand() 함수로 생성한 난수는 항상 동일하게 나온다.
- 따라서 완전히 랜덤한 난수 값을 생성하기 위해서는 srand()로 시드 값도 변경해 줄 필요가 있음
예시)
#inlcude<stdio.h>
#include<stdlib.h>
int main(){
// 0. 시드값이 동일할 때 첫번째 난수 값 확인해보기
for (int i = 0; i<5; i++){
srand(30000); // 시드값 30000 고정
printf("%d", rand()); // 시드값 30000의 첫 난수
}
// 1. 시드값 변경하면서, 난수 생성
for (int i = 0; i<5; i++){
srand(i); // 시드값 변경
printf("%d", rand());
}
return 0;
}
(3) time() 함수
- <time.h>에 선언되어 있음
- 현재 시스템의 시간에 의해 결정되는 정수 리턴
- 실행할 때마다 시드를 바꾸기 위해서 사용
예시) 실행할 때 마다 시드값을 랜덤하게 바꾸기
#inlcude<stdio.h>
#include<stdlib.h> // rand 함수 사용을 위해
#include<time.h> // time 함수 사용을 위해
int main(){
srand( time(NULL) ); // 시드를 현재시간으로 지정
// 시드가 시간에 따라 매번 바뀌어 완전히 랜덤한 난수 생성
for (int i = 0; i<5; i++){
printf("%d", rand());
}
return 0;
}
(4) min 이상 max 미만의 난수 생성하기
>> rand() / ((double)RAND_MAX +1) * (max-min) + min
- rand() : 0~RAND_MAX 사이의 임의의 정수 생성
- / ((double)RAND_MAX +1) : 생성된 정수를 [0, 1) 사이의 소수로 변환
- * (max-min) : [0, 1) 사이의 소수를 [0, max-min) 사이의 값으로 변환
- + min : 수를 min 만큼 이동시켜, [min, max) 사이의 수로 변환
2) 실행시간 측정
- clock() 함수 사용
- <time.h>에 선언되어 있음
- 호출 당시의 시스템 시각을 CLOCKS_PER_SEC (time.h에 정의된 상수) 단위로 반환
- 초 단위의 시간을 얻기 위해서는 clock() 함수에 의해 측정된 시각을 CLOCKS_PER_SEC로 나누어야 함
예시) 난수 생성 함수 실행시간 측정
#inlcude<stdio.h>
#include<stdlib.h> // rand 함수 사용을 위해
#include<time.h> // time 함수 사용을 위해
int main(){
clock_t start, finish;
double duration;
start = clock(); // 시작 시각
srand( time(NULL) ); // 시드를 현재시간으로 지정
// 시드가 시간에 따라 매번 바뀌어 완전히 랜덤한 난수 생성
for (int i = 0; i<5; i++){
printf("%d", rand());
}
finish = clock(); // 종료 시각
duration = (double)(finish - start) / CLOCKS_PER_SEC; // 실행시간 계산
printf("실행 시간: %lf 초\n", duration); // 실행시간 출력
return 0;
}
'프로그래밍 언어 개념정리 > C언어 개념 정리' 카테고리의 다른 글
C언어 개념 정리: 파일 입출력 (0) | 2024.12.09 |
---|---|
C언어 개념 정리: 동적 할당 (0) | 2024.11.18 |
C언어 개념 정리: 구조체 (0) | 2024.11.15 |
C언어 개념 정리: 문자열 (1) | 2024.11.13 |
C언어 개념 정리: 포인터 (0) | 2024.11.12 |