본문 바로가기
학습/IT

[IT] C언어 입문(8) Scope rules/recursion, 변수의 영역규칙과 재귀호출, 난수생성 예시

by 개성공장 2021. 8. 26.
반응형

□ scope rules/recursion

 

 * Call by Value Revisited

 - 함수를 사용하기 위해 미리 선언해두는 것

 - 함수의 이름, 변수 타입

 

int sum(int n);
{
	int s=0
	for( ; n>0; n--)
		s += n;
	return s;
} // 1부터 n까지의 값을 모두 더함

 

#include<stdio.h>
int sum(int m);   // 함수를 사용하기 위해 미리 함수명과 타입을 선언

int main(void)
{
	intn=5;
	printf("sum= %d\n", sum(n));   // n이라는 변수가 넘어가는 것이 아닌, 5라는 값(value)가 함수로 넘어감
	printf("n=%d\n",n);
	return 0;
}

 

- 참고 : for(;;)  => 무한루프

 

 

 * Large Program Development

 - A large program is written in a separate directory with many .c and .h files

 - 사용자가 직접 헤더파일을 작성

 - 리눅스 커널 같은 거대한 프로그램은 수많은 라이브러리, 헤더파일 등으로 구성, 모듈화

 

 * Assertions

 - In the form of, : assert( expr )

 - In the standard header file 'assert.h'

 - If expr is 0, the system will print a message, and the program will be aborted

 - 조건식을 만족하지 못하면 프로그램을 중간에 (assert 부분에서) 종료

 - example

int main(void)
{
	int a, b;
	...
	b=foo( a );
	assert( b>0 );
}

 

 

 * Scope Rules

 - Identifiers(식별자) are accessible only within the block in which they are declared.

 - Local variables : Declared within a block, Stored at a temporary storage(typically stack), Generated at the start of a block and destroyed at the end of the block, Values are undefined if not explicitly defined.

 - Global variables : Variables declared outside a function, Stored at a permanent storage for the lifetime of the program, Values are set to 0 if not explicitly defined.

 

 - example

int x;   // global variables
int main(void)
{
	int a = 1, b = 2;  // local variables
}

 

 * Auto and Extern Storage Classes

 - auto : Variables declared within function bodies and blocks (함수의 body 부분에서 선언되는 변수, 생략됨)

 ex) auto int a, b, c;

 - extern : Variables declared outside a function, extern tells the compiler to look for the variable in this file or some other file

 ex) extern int a, b, c;

 

 - example

main.c

================

int a, b, c;
void foo(void)
int main(void)
{
	a = b = c = 1;
	foo();
	printf("%d%d%d\n", a, b, c);
	return 0;
}

 

foo.c

=================

void foo(void)
{
	extern int a;
	int b, c;

	a = b = c = 4;

	return;
}

 

=> main.c 결과값 : 4, 1, 1

 

 

 * Register and Static Storage Classes

 - register : Tells the compiler that the variable should be stored in a register if possible

 - For performance (레지스터는 CPU에 내장된 메모리로 속도가 매우 빠름)

 - ex) register int i;

 

 * static : To make a local variable to retain its value when the block is reentered

 - or to use a variable as a local variable to the file it is declared.

void foo(void)
{
	static in cnt = 0;
	cnt++;
}

 

 

 - Visible only within the file in which they are defined

(static이 함수 이름 앞에 사용되는 경우)

static int foo(void)
void bar(void)
{
	... foo() ...
}
static int foo(void)
{
	...
}

 => extern 등을 이용해서 함수 내용에 접근(access)하는 것을 막음

 

 

 Recursion(재귀호출)

 - A function is said to be recursive if it calls itself, either directly or indirectly.

int sum(int n)
{
	if(n<=1)
	return n;
	else
	return(n + sum(n-1));   // 함수 내부에서 자기 자신을 다시 호출하는 형태
}

 => n에 5라는 값을 넣었을 때, sum(5)=5+4+3+2+1=15,

참일 때 값을 n에서 1로, +를 *로 바꾸면 팩토리얼이 계산됨

 

 * Recursion vs Iteration

---

int fact(int n)  // recursion
{
	if(n<=1) return 1;
	else return (n * fact(n-1));
}

VS

int fact(int n)  //for loop(iteration)
{
	int r = 1;
	for(; n>1; n--)
		r *= n;
	return r;
}

---

 - 두 코드는 동일하게 팩토리얼을 계산하는 코드이나 직관성을 고려하면 recursion이 유리(수학의 수열 표현에 있어서, f(n)=f(n-1)*n 이런 식)

 - 최적화 측면에서는 밑의 for loop문이 더 유리

 

 

 * 예시

 - Write a coin-tossing program that uses the random-number generator rand() in the standard library to simulate the toss

 

---

#include <stdio.h>
#include <stdlib.h>    //rand() 함수가 선언되어 있음
#include <assert.h>
#include <time.h>     //time() 함수 선언
int main(void)
{
	int a, b, i, cnt = 0;
	srand(time(NULL));
	for(i=0; 1<1000; i++)
	{
		a = rand() % 5 + 1;    // 1부터 5 사이의 랜덤 숫자 생성
		b = rand() %10 + 1;   // 1부터 10 사이의 랜덤숫자 생성
		if(b - a <= 1)
			continue;
		assert(b - a > 5);
		printf("%4d\n", ++cnt);
	}
}

 

 - 시스템에서 만들어주는 랜덤 숫자는 pseudo random number로 초기값을 알면 생성되는 난수가 계산될 수 있음

 - 진짜 랜덤 숫자를 만들기 위해 seed value를 주는 srand와 time함수를 사용

 

---

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

main()
{
	srand(time(NULL));

	if(rand() % 2) { printf("Head\n");
	} else { printf("Tail\n");
	}
}

 

※ C언어 입문 시리즈
1. Introduction - C언어의 역사와 기본 개념
2. Variables - 변수, 대입연산자, 구문규칙, 데이터타입 등
3. Data types, 데이터 타입(자료형)
4. Operators, 연산자 - scanf, 산술연산자, 관계연산자, 증감연산자, 대입연산자, 동등연산자 등
5. Operators, 연산자 - 논리연산자, 단축평가, 대입연산자, if문 및 while문 활용
6. Control flow, 제어흐름 - While문, For문, If문, do-while문 등 루프문
7. Function, 함수 - Goto문, getchar와 putchar, 함수 정의와 프로토타입 선언
8. Scope rules/recursion, 변수의 영역규칙과 재귀호출, 난수생성 예시
9. Array와 Pointers, 배열과 포인터
10. Pointer, 역참조, swap 함수 활용, 배열과 포인터 비교
11. File operation 파일연산, String, 다차원 배열 예시
12. structure, union, enumerated types - 구조체, 공용체, 열거체
13. 자료구조(data structure) 예시 - 연결리스트(linked list)
14. C 전처리기(C preprocessor), 함수 포인터(function pointer)
반응형

댓글