티스토리 뷰

2021.03.01.월

레지스터 변수

✔  예약어 register과 함께 변수를 선언하면, 변수는 메모리 공간 대신 CPU 내부의 저장공간인 레지스터를 사용한다.

✔  사용 횟수가 많은 변수의 경우 레지스터에 할당하면 실행 시간을 줄일 수 있다. (예) 반복문

#include <stdio.h>

int main() {    
  register int i;
  int sum;

  //레지스터 변수를 사용한 반복문
  sum = 0;
  for (i = 1; i <= 10000; i++){
    sum += i;                
  }

  return 0;
}

✔  레지스터의 사용 여부는 컴파일러가 결정한다.

✔  레지스터는 중요한 저장 공간이므로, 당장 연산할 필요가 없는 데이터를 레지스터에 보관하면 활용성이 떨어진다.

✔  그렇기 때문에 컴파일러는 레지스터와 메모리 중 더 적합한 저장 공간을 선택한다.

✔  레지스터의 공간은 크지 않으므로 2개까지만 선언할 수 있다.


✔  레지스터 변수는 잠시 동안만 CPU 내부의 저장 공간을 빌릴 수 있다.

✔  즉, 프로그램이 종료될 때까지 계속 공간을 확보할 수 없기 때문에 전역 변수로는 사용할 수 없다.

#include <stdio.h>
 
register int i; //오류 발생

int main() { 
  register int num = 10;
  printf("%p", &num);
  return 0;
}

✔  레지스터 변수는 CPU 내부 공간인 레지스터를 사용하기 때문에 별도의 메모리 공간을 할당받지 않는다.

✔  그렇기 때문에 메모리 공간 주소를 구하는 주소 연산자 &를 사용할 수 없다.

✔  일부 컴파일러는 레지스터 변수를 auto 변수로 변환해서 해석해 주소연산자 &를 사용할 수 있다.

#include <stdio.h>
 
int main() { 
  register int num = 10;
  printf("%p", &num); //오류 발생
  return 0;
}

✔  레지스터는 CPU 내부에 있어서 데이터 처리 속도가 매우 빠르다.

✔  그래서 <time.h> 헤더 파일에 포함된 clock() 함수를 사용해 실행 시간을 확인해 보았다.

✔  실행할 때마다 조금씩 달라지기는 했지만, 결과적으로 레지스터 변수가 더 빠르다는 것을 확인할 수 있었다.

#include <stdio.h>
#include <time.h>
 
int main() {    
  //시간 측정에 필요한 변수 선언
  clock_t start1, end1, start2, end2;
  double result1, result2;  
  
  //레지스터 변수와 지역 변수 선언
  register int i;
  int j;
  int sum;
  
  start1 = clock(); //시간 측정 시작    
  sum=0;
  //레지스터 변수를 사용한 반복문
  for (i = 1; i <= 10000; i++){
    sum += i;                
  }  
  end1= clock(); //시간 측정 끝
  
  start2 = clock(); //시간 측정 시작  
  sum=0;
  //일반 지역 변수를 사용한 반복문
  for (j = 1; j <= 10000; j++){
    sum += j;                  
  }
  end2= clock(); //시간 측정 끝

  //끝 시간 - 시작 시간 = 총 실행시간
  result1 = (double)(end1 - start1);
  result2 = (double)(end2 - start2);

  //초 단위로 나오게하기위해 CLOCKS_PER_SEC로 나누어줌
  printf("레지스터 변수 사용 시, 실행 시간 : %f\n", result1/CLOCKS_PER_SEC);
  printf("일반 지역 변수 사용 시, 실행 시간 : %f\n", result2/CLOCKS_PER_SEC);  

  return 0;
}

 

 

값을 복사해서 전달하는 방법

✔  함수를 호출하면서 인자를 전달하게 되면, 인자의 값이 복사되어 함수에 전달된다.

✔  이러한 방식을 사용하면 실제 변수 값은 변하지 않는다.

✔  원본 데이터를 보존할 수 있으므로 안정적이다.

#include <stdio.h>

void swap(int a, int b);

int main(void){
  int a=10, b=20;
  swap(a,b);
  printf("a = %d, b = %d", a,b);
  //a = 10, b = 20;
  return 0;
}

void swap(int a, int b){
  int temp=a;
  a = b;
  b = temp;
}

 

 

주소를 전달하는 방법

✔  함수를 호출할 때 변수의 주소를 넘기면 호출한 함수에 있는 변수의 값에 접근해 수정이 가능하다.

✔  다만 포인터 연산으로 값을 처리해야 하므로 조금 불편하다.

✔  값을 복사해 사용하는 것이 아닌 값의 주소를 가져오는 것이기 때문에 같은 값을 공유한다.

✔  원본 데이터에 접근할 수 있지만, 절대 바꾸면 안 되는 데이터를 다루는 경우 문제가 생길 수 있으니 주의하자.

#include <stdio.h>

void swap(int *a, int *b);

int main(void){
  int a=10, b=20;
  swap(&a,&b);
  printf("a = %d, b = %d", a,b);
  //a = 20, b = 10;
  return 0;
}

void swap(int *a, int *b){
  int temp=*a;
  *a = *b;
  *b = temp;
}

 

 

주소를 반환하는 함수

✔  함수가 종료된 후에도 변수의 저장 공간이 계속 유지된다면, 주소를 반환함으로 해당 변수에 접근할 수 있다

✔  만약 함수가 종료되어도 할당받은 공간이 해제되지 않는다면 주소를 알고 있을 때 계속 사용할 수 있다.

✔  즉, 정적 지역 변수(static)이나 전역 변수를 사용하면 해당 변수의 주소를 알고 있는 경우 계속 접근할 수 있다.

#include <stdio.h>

int* sum(int a, int b);

int main(void){
  int a=10, b=20;
  printf("a + b = %d", *sum(a,b));
  return 0;
}

int* sum(int a, int b){
  static int sum;
  sum = a+b;
  return &sum;
}

 

 

 

 

 

[참고] 한빛미디어-혼자 공부하는 C언어 유튜브 강의 / 엘리스 트랙-혼자 공부하는 C언어 / 길벗-C언어 코딩 도장 / 위키백과

 

댓글
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
최근에 올라온 글
글 보관함
Total
Today
Yesterday