HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
장지원 페이지/
🗑️
Trash
/
장지원, JANG JIWON
장지원, JANG JIWON
/C언어/
Week2

Week2

2023.07.04 to 2023.07.10

 
 

1. 배열

배열의 기초
 

개념

 
많은 양의 데이터를 한 번에 다루기 위해 사용
 
  1. 배열의 선언
int a[5]; 와 같은 식으로 만들 수 있음
이 때 5를 배열의 크기, a[0], …, a[4]를 배열의 요소 라고 부름
 
배열의 요소는 일반 변수 처럼 사용될 수 있음 → printf, scanf로 출력 또는 입력 가능함
[]안에는 정수 값이 나오는 연산이 들어갈 수도 있음
(참고, []안에 있는 정수는 ‘첨자’라고 부름)
 
다섯 명의 점수를 입력 받아서 출력하기
#include <stdio.h> int main(void){ int a[5]; int i; for (i=0; i<5; ++i) { scanf("%d", &a[i]); } for (i=0; i<5; ++i) { printf("%d\n", &a[i]); # C에서 printf는 줄 바꿈을 가지고 있지 않아 ! 명심하기 } return 0; }
 
다섯 명의 점수를 입력 받아서 합 구하기
#include <stdio.h> int main(void){ int a[5]; int i, sum; # 자신이 쓸 변수 모두 미리 만들어주어야 하는 것도 명심하기 sum = 0; for (i=0; i<5; ++i) { scanf("%d", a[i]); } for (i=0; i<5; ++i) { sum = sum + a[i]; } printf("%d", sum); return 0; }
배열의 활용
 

개념

 
배열을 활용한 계산과 배열 사이에 연산을 진행
 
배열의 값을 저장하는 방법
만약 규칙성이 있는 값들이라면 반복문을 통해 값을 넣어도 됨
그러나 규칙성이 없다면? → int a[5] = {2,5,4,3,0} 이런 식으로 저장할 수 있음
이런 식으로 배열을 선언하면서 값을 대입하는 것을 ‘초기화’라고 함
배열이 선언 된 이후에는 이 과정을 진행할 수 없음
만약 초기화 할 때 배열의 크기보다 값을 적게 할당하면, 나머지 값들은 0이 되어 저장됨
만약 값만 할당 되어있고 배열의 크기가 정해지지 않았다면, 할당 된 값 개수 만큼 배열의 크기를 지정해줌
 
배열의 초기화와 배열 사이 연산
#include <stdio.h> int main(void){ int a[5] = {2,5,4,3,0}; int b[5], c[5]; int i; for (i=0; i<5; ++i) { b[i] = a[i]*2; } for (i=0; i<5; ++i) { c[i] = a[i] + b[i]; } return 0; }
배열에는 다양한 자료형이 들어갈 수 있음
배열 0부터 시작한다는 것 명심하기
double a[5]; char a[5]; 이렇게 선언하면 됨
 
 
다차원 배열
 

개념

 
말 그대로 다차원 배열
 
선언은 int a[2][3]; 처럼 할 수 있음 → 행이 2개이고, 열이 3개인 배열이 만들어짐
이 때, 각 배열에 요소에는 a[0][0], a[0][1], … 의 이름이 붙게 됨
 
# include <stdio.h> int main(void){ int a[2][3]; a[0][2] = 5; a[1][1] = a[0][2]*2; printf("%d\n", a[1][1]); return 0; }
ㅤ
ㅤ
5
ㅤ
10
ㅤ
→ 현재 배열에는 이 값들이 저장되어 있을 것
 
다차원 배열에서는 반복문을 쓸 때 중첩 반복문을 사용해야해 → 값이 두 개니까 당연하겠지?
 
for문을 사용한 2차원 배열에서의 입력과 출력
# include <stdio.h> int main(void){ int a[2][3]; int i, j; for (i=0; i<2; ++i) { for(j=0; j<3; ++j) { scanf("%d", &a[i][j]); } } for (i=0; i<2; i++) { for (j=0; j<3; j++) { printf("%d", a[i][j]); } } return 0; }
(지금은 가로 한 줄로 출력 됨) 세로 한 줄로 출력하고 싶거나, 행과 열에 맞춰서 출력하고 싶다면 \n 넣는 위치 바꾸면 됨
 
 
다차원 배열의 활용
 

개념

 
이런 식의 활용도 가능하구나 !!
#include <stdio.h> int main() { int numArr[3][4] = { // 세로 크기 3, 가로 크기 4인 int형 2차원 배열 선언 { 11, 22, 33, 44 }, { 55, 66, 77, 88 }, { 99, 110, 121, 132 } }; int col = sizeof(numArr[0]) / sizeof(int); // 4: 2차원 배열의 가로 크기를 구할 때는 // 가로 한 줄의 크기를 요소의 크기로 나눠줌 int row = sizeof(numArr) / sizeof(numArr[0]); // 3: 2차원 배열의 세로 크기를 구할 때는 // 배열이 차지하는 전체 공간을 가로 한 줄의 크기로 나눠줌 for (int i = row - 1; i >= 0; i--) // 세로 크기 - 1부터 역순으로 반복 { for (int j = col - 1; j >= 0; j--) // 가로 크기 - 1부터 역순으로 반복 { printf("%d ", numArr[i][j]); // 2차원 배열의 인덱스에 반복문의 변수 i, j를 지정 } printf("\n"); // 가로 요소를 출력한 뒤 다음 줄로 넘어감 } return 0; }
sizeof 키워드를 이용해 배열의 크기 구하기
 
2차원 배열의 여러가지 합
2차원 배열에서 특정 열, 모든 열, 특정 행, 모든 행, 전체 배열 .. 등 다양한 합을 구할 수 있음 → 나중에 필요하다면 스스로 해보기
 
2차원 배열의 초기화
파이썬처럼 두 번 묶어주면 됨 → 대신 중괄호를 이용해서 묶어주기 !!
int a[2][3] = {{0,1,2},{3,4,5}}와 같이 사용하면 됨
이걸 간단히 해서 int a[2][3] = {0,1,2,3,4,5}를 이용할 수도 있음
이 경우에는 [0][0]부터 차례대로 대입해줌 → 헷갈리니까 걍 위에 방법 써;;
 
일 차원 배열에서와 마찬가지로 값이 주어지지 않으면 0을 할당해줌
 
단, int[][3] = {{0,1},{3}};는 가능하지만, int[3][] = {{0,1},{3},{4}}; 는 안됨 → 즉, 첫 번째 크기만 생략될 수 있음
 
마지막으로 a[][3] = {1,2,3) 이라면 행은 한 개가 됨 (초기화 값을 모두 넣을 수 있는 최소 행의 개수로 정해짐)
 
 

2. 함수

함수의 기초
 

개념

 
함수 → 프로그램 일부를 분리한다(?)
→ 그리고 main에서 실행한다?
 
→ 음 뭔가 파이썬과 완~~전히 동일한 개념은 아닌 듯
파이썬은 추상화가 목적이라면, C언어는 추상화가 목적..? ;;;
음.. 비슷한데 다른 것 같은 느낌
 
밑의 그림 참고하기
 
notion image
 
함수 작성
함수를 작성할 때는 main 함수 밖에서 작성해야 함
 
#include <stdio.h> int avg(int a, int b){ int c; c = (a+b)/2; return c; } int main(void){ int aa, bb, cc; scanf("%d", &aa); scanf("%d", &bb); cc = avg(aa, bb); printf("%d\n",cc); return 0; }
int a, int b는 파라미터임
avg 함수에서 반환 값이 int이기 때문에 int avg라고 쓰는 것 → 아 ! main 함수도 반환 값이 0이기 때문에 int로 쓰는 구나 !
 
프로그램이 시작 될 때는 무조건 main 함수 먼저 실행 됨
함수의 정의와 호출
 

개념

 
함수의 정의
함수의 이름, 함수의 몸체, 반환 값의 자료형, 매개 변수 → 이 네 가지가 기술 되어야 함
 
함수의 호출
함수 이름, 인자
 
→ 파이썬에서와 동일
 
두 입력 받은 수 중 더 큰 수를 print 해주는 프로그램
#include <stdio.h> int max_int(int a,int b){ if (a < b){ return b; } else{ return a; } } int main(void){ int a,b,c; scanf("%d",&a); scanf("%d",&b); c = max_int(a, b); printf("%d\n", c); return 0; }
함수 주의 사항
 

개념

 
함수 사용 시 주의 사항
 
scope 주의하기 → 다른 namespace에 있으면 같은 이름을 가진 변수를 선언할 수 있음
 
scope
#include <stdio.h> int avg(int a, int b){ int c; c = (a+b)/2; a = 8; # 이 a는 반환 값이 아니므로 main 함수에 어떠한 영향도 주지 않음 return c; } int main(void){ int a,b,c; a = 20; b = 12; c = avg(a,b); printf("%d %d %d\n", a, b, c); # ,를 붙여주지 않았으므로 20 12 16이 출력 됨 (20,12,16 X) return 0; }
 
변수의 소멸 : 함수가 종료되면 변수가 소멸굄
 
함수의 위치 : 함수는 사용하기 전에 정의 또는 선언되어 있어야 함
즉, 위의 예시처럼 작성해야 함, 만약 밑의 예시처럼 작성한다면 오류가 생길 것
(밑의 예시는 간단해서 오류가 발생하지 않지만, 코드가 길어진다면 문제가 발생할 수 있음)
 
#include <stdio.h> int main(void){ int a,b,c; a = 20; b = 12; c = avg(a,b); printf("%d\n",c); } int avg(int a, int b){ int c; c = (a+b)/2; a = 8; return c; }
함수를 만드는 부분이 코드에서 위치적으로 더 위에 기술되어야 한다
 
그러나 가독성이 떨어진다는 단점이 있음 → ‘함수 선언’ 이라는 과정을 통해서 가독성을 높여줌
함수 선언은 함수의 내용은 기술하지 않고 머리 부분만 적어 놓은 것
이 부분을 함수의 ‘원형’ prototype 이라고 함
함수의 원형만 가지고도 호출이 가능한 이유는 함수를 ‘호출할 때 필요한’ 정보들이 원형에 모두 들어있기 때문임
함수 선언 할 때는 매개변수 안 적어도 됨 → 밑 예시의 둘째 줄에 int avg(int a, int b) = int avg(int, int)로 적어도 됨 → 호출하는 입장에서는 매개변수의 개수와 자료형만이 중요하기 때문에 !
 
#include <stdio.h> int avg(int a, int b); # int avg(int, int)로 적어도 같은 의미를 가짐 int main(void){ int a,b,c; a = 20; b = 12; c = avg(a,b); printf("%d\n",c); } int avg(int a, int b){ int c; c = (a+b)/2; a = 8; return c; }
 
이렇게 함수 선언을 미리 해두면 main 함수가 위에 있고, 함수를 기술하는 부분이 밑에 정의되어도 문제가 생기지 않아
 
void : 함수의 반환 값이 존재하지 않는다는 의미
이 때는 return; 이 오거나 아무것도 오지 말아야 함 → return 0;은?
void가 매개 변수 자리에 있다면, 매개 변수가 없다는 의미를 가짐 → 호출 할 때 인자도 적지 말아야겠지?
 
 
 
 
main 함수와 시스템 라이브러리 함수
 

개념

 
main 함수
: 프로그램이 실행될 대 제일 먼저 실행되는 함수
 
int main(void)
→ 매개 변수는 없고, 반환 값이 int형인 함수 → return 0; 이라고 적었던 것임
main함수를 마쳤을 때 어디로 돌아가고 반환 값이 어떤 역할을 하는지에 대해서는 나중에 !!
return 0;을 적지 않아도 됨 → 아무것도 적지 않아도 실행 됨
 
시스템 라이브러리 함수
printf, scanf 등.. printf에서 “%d”, a 같은 것이 이 시스템 라이브러리 함수의 파라미터
 
이 함수들의 정의는 컴퓨터의 시스템 또는 운영 체제, 컴파일러 안에 되어있음
→ 우리는 호출만 해주면 됨
 
이 함수의 선언은 stdio.h 파일 안에 들어있음
그래서 #include <stdio.h>를 항상 정의 해주었던 거임 → 이것의 의미는 stdio.h 파일을 가져와서 그 자이 안에 넣어라 → 이 파일에 printf 등의 선언이 들어 있고, 그 파일을 #include <stdio.h>를 통해 프로그램에 넣어왔던 거임
 
(우리가 정의하는 함수는 ‘사용자 정의 함수’라고 부름)
 
밑 사진은 다양한 시스템 라이브러리 함수
 
notion image
 
#include <> 괄호 안에 헤더 파일을 입력함으로써 선언
 
수학 함수
math.h 헤더 파일을 이용함
 
수학 함수 - 삼각 함수
수학 함수에서 파이썬은 라디안 값을 이용함 → 2pi 이런 식으로 → 근데 각도 쓸 수 없으니까 당연하겠지 ?
 
#include <stdio.h> #include <math.h> int main (void){ double pi = acos(-1.0); printf("%f", sin(pi/6)); printf("%f", cos(pi/3)); printf("%f", tan(pi/4)); }
 
acos = arcos 즉, cos이 역함수임
따라서 pi에는 3.14… 파이 값이 저장되게 됨
 
수학 함수 - 올림/내림 함수
올림 함수 : ceil(2.3) → 3.0 / 내림 함수 : floor(2.3) → 2.0
→ 이 두 함수의 반환 값은 double 이므로 “%f”로 출력 해주어야 해
 
반올림 함수는 존재하지 않음 floor(x+0.5) 형태로 반올림의 기능하게 만들 수 있음
 
→ 앞으로의 확대 only main 함수 → 사용자 정의 함수 추가 → 추가 다른 파일 → 구조체 등과 결합한 객체지향
 

3. 함수 2

매개 변수가 1차원 배열인 함수
 

개념

 
#include <stdio.h> int array_sum(int a[5]){ # a는 매개변수이므로 a에 대해 정의 할 필요는 없음 int i, sum; sum = 0; for (i=0; i<5; i++){ sum += a[i]; } return sum; } int main(void){ int b[5] = {10,2,3,7,9}; printf("%d\n", array_sum(b)); return 0; }
 
매개 변수가 배열인 것은 전에 배웠던 것과 약간의 차이를 가짐
 
notion image
notion image
 
배열의 복사 되어서 파라미터 위치로 가는 것이 아님 → 값을 그대로 참조한다고 생각하기
파이썬에서 copy와 =을 사용한 것의 차이가 있는 것과 같다고 해석하기
 
여기서 문제가 생김 위 예시에서 a[2] = 8; 이라는 문장을 추가했다고 가정해보자
a는 b의 값의 참조와 동일하므로 b[2]도 8로 바뀔 것이다
 
값에 의한 호출에서는 함수를 부를 때 값만 복사 됨 → 그러므로 함수를 부른 쪽의 변수가 바뀔 리는 없어
→ 그러나 매개 변수가 배열인 함수에서는 함수에서의 동작에 의해 함수를 부른 쪽에 있는 배열 요소 값이 바뀔 수 있음
 
지금은 그냥 값에 의한 호출과 배열에 의한 호출에 차이가 있다고 알아두기 → 나중에 포인터 할 때 더 자세히 배울 것
 
매개 변수가 배열일 때는 배열을 새로 만드는게 아님 → 단순히 인자에 있는 배열에 이름만 붙이는 것
그러므로 크기를 정의하는 것은 좀 불필요해 보임 → 실제로 컴퓨터(컴파일러)에서도 배열 매개 변수에 지정되어있는 크기를 무시함
그러므로 int array_sum(int a[])와 같이 크기를 지정해주지 않는 것이 일반적임
 
어떠한 크기의 1차원 배열도 인자로 가능함
즉, 배열 매개 변수에서는 크기를 지정하지 않고, 대신 처리할 크기를 따로 매개 변수로 받아서 그 매개 변수에 저장된 값만큼 함수 내부에서 처리하는 것이 배열 매개 변수를 가지는 함수의 일반적인 형태임
 
#include <stdio.h> int array_sum(int a[], int n){ int i, sum; sum = 0; for (i=0; i<n; ++i){ sum += a[i]; } return sum; } int main(void){ int b[5] = {10,2,3,7,9}; int c[7] = {1,3,5,7,9,11,13}; printf("%d\n", array_sum(b, 5)); printf("%d\n", array_sum(c, 7)); return 0; }
이렇게 크기를 따로 지정 받고 그 크기를 이용하는 식으로 활용 !
 
 
 
 
 
 
매개 변수가 다차원 배열인 함수
 

개념

 
일차원 배열에서와 마찬가지로 크기 무시 가능 → 단, 첫 번째 크기만 무시 가능
int a[][3]과 같이 두 번째 요소는 적어주어야 해
 
#include <stdio.h> int array_sum(int a[][3], int n){ int i, j, sum; sum =0; for (i=0; i<n;, i++){ for (j=0; j<3; j++){ sum = sum + a[i][j]; } } return sum; } int main(void){ int b[2][3] = {{3,2,3}{2,3,4}}; printf("%d\n", array_sum(b, 2)); }
이렇게 첫 번째 요소의 크기만 생략 가능
 
첫 번째 크기가 생략 가능하다 = 행의 개수가 자유롭다는 뜻으로 해석해도 됨
 
당연하지만 열의 개수가 다른 것은 사용 불가능 → int a[][3]에 int b[2][3]은 가능하지만 int b[2][4]는 불가능 할 것
 
→ 행과 열의 개수가 자유로운 배열에 대한 매개 변수는 존재하지 않음
포인터에서 이를 특별한 방법으로 다루는 것은 가능
 
2차원 말고, 3차원, 4차원 등의 배열에서도 위 특징은 마찬가지로 적용 됨
재귀 함수
 

개념

 
자기 자신을 호출하는 함수
 
예제
int fact(int a){ int mul; if(a>=2){ mul = a* fact(a-1); } else { mul = 1; } return mul; )
a가 1일 때는 1을 반환 함
 
예제
#include <stdio.h> int fact(int a); # 직관성을 위한 선 정의 int main(void){ int res; res = fact(5); printf("%d", res); } int fact (int a){ int mul; if (a>=2){ mul = a*fact(a-1); } else { mul = 1; } return mul; }
 
밑 사진과 같이 동작한다
 
notion image
 
 
재귀 함수에서의 주의 사항
→ 코드 해석에 유의하기 → 굉장히 헷갈림
 
초항이 1이고 점화식이 a(n번째) = 2a(n-1번째) + 1 인 수열을 표현한 재귀 함수
#include <stdio.h> int tt(int n); int main(void){ int a; a = tt(20); printf("%d", a); } int tt(int n){ int res; if (n == 0){ res = 1; } else { res = 2*tt(n-1) + 1; } return res; }
 
위 예제들은 재귀 함수로 굳이 쓰지 않아도 구현 가능함
반복문을 사용하면 재귀 함수를 쓰지 않아도 문제를 해결 할 수 있음
→ 그러나, 재귀 함수를 사용할 때 더 명료해지는 프로그램들도 있기 때문에 이를 사용함
특히 하노이 탑 문제는 재귀 함수를 적용 하면 아주 쉽게 풀림
 
 
난수 발생 함수
 

개념

 
난수 발생 함수란?
시스템 라이브러리 함수 중 가장 많이 이용하는 함수
 
난수 = random number
 
그러나, 컴퓨터는 항상 예측이 되도록 발명 되었기 때문에 진정한 의미의 난수 생성은 불가능함
 
그래서 어떤 규칙을 갖고 난수를 생성함 (뭐.. 우리가 알지 못하지만 컴퓨터가 생성하는 난수에는 규칙이 있다 정도만 이해하기) → 그리고 그 난수들을 저장해 놓음 → 저장 된 난수들이 모여있는 줄에 붙어있는 번호를 seed라고 부름
 
rand() 함수를 통해 난수 생성 가능 → 0~32767 범위에서 난수가 생성됨
이 함수는 stdlib.h 헤더 파일에 저장되어 있음
 
#include <stdio.h> #include <stdlib.h> int main(void){ int a, i; for (i=0; i<10; ++i){ a = rand(); printf("%d\n", a); } }
++i, i++ 차이.. 빨리 알고 싶다..
 
이 프로그램을 실행시켜 보면 10개의 난수가 출력 되어서 나옴
→ 그러나 계속 출력 시켜 보면 똑같은 수가 계속 출력 되는 것을 확인할 수 있음
컴퓨터가 저장된 난수를 하나씩 순서대로 읽는 방식으로 난수를 출력해주기 때문임
 
파이썬에서 seed 설정해주듯이 srand() 함수를 통해 seed 지정해줄 수 있어
 
#include <stdio.h> #include <stdlib.h> int main(void){ int a, i; srand(2); for (i=0; i<10; ++i){ a = rand(); printf("%d\n", a); } }
 
단, seed 값 계속 바꾸어줘야 난수 계속 바뀜
 
그런데, 이렇게 seed 실행할 때 마다 바꾸어주는 것은 곤란해
그럴 때 사용하는 것이 time() 함수임
이 함수는 1970년 1월 1일에서 호출 시점까지 흐른 시간을 초 단위로 반환해줌
이 함수는 time.h 헤더 파일을 이용해 호출해주면 되고, 인자는 NULL을 넣어주면 됨 → NULL넣어야 하는 이유는 복잡하므로 설명하지 않았음
 
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(void){ int a, i; srand(time(NULL)); for (i=0; i<10; ++i){ a = rand(); printf("%d\n", a); } }
 
마지막으로 난수를 우리가 원하는 범위로 바꾸는 법
 
0~9 사이의 난수를 발생 시키고 싶다면 → rand()%10
10으로 나눈 나머지 이므로 당연히 0~9사이 값이 출력 되겠지?
 
1~10 사이의 난수를 발생 시키고 싶다면 → rand()%10+1
 
이런식으로 a~b 범위의 난수를 발생시키고 싶다면 rand()%(b-a+1)+a 라고 하면 됨
 
작은 범위의 난수는 위와 같은 방법으로 생성할 수 있음
 
큰 범위의 난수를 위와 같이 생성하면 각 수 마다 생성 확률이 너무 크게 차이나게 됨
(나머지가 0~2 인 것은 많을 테고, 99~110 인 것은 적을 테니까 → 너가 수학적으로 생각해봐)
→ 이건 생성할 일 있을 때 직접 찾아봐 ^^ 책 설명 너무 이사암
 
마지막으로 실수 범위의 난수 0~1까지의 범위의 난수를 출력시키고 싶다면
rand()/32768 해주면 됨
 
 

4. 변수 범위

문장과 블록
 

개념

 
원래 C언어에서 for문과 if문을 쓸 때는 {} 중괄호 쓰지 않음 (아 ~ 뒤에 한 개의 문장만 온다면 중괄호 안 써도 되는구나)
→ 그러나 if문 for문 뒤에 두 문장 이상 써야 할 때 중괄호를 사용하는 것임
이 중괄호로 둘러 쌓인 부분을 블럭(block) 이라고 함
 
웬만하면 중괄호 써주자 !!
코딩 스타일과 들여쓰기
 

개념

 
공백을 보기 좋게 사용할 수도 있음 → 들여쓰기 (indentation)
 
중괄호도 사람마다 다르게 쓸 수 있음
for (i=0; i<5; i++) {
}
 
for (i=0; i<5; i++)
{
}
 
어떻게 쓰든 상관없음 → 단, 밑의 방법으로 쓰면 가독성이 좋다는 장점이 있지만, 코드가 위, 아래로 길어진다는 단점 또한 존재함.
 
변수 이름도 쓰임에 맞게 사용하는 것이 좋음
변수 범위
 

개념

 
#include <stdio.h> int avg(int a, int b){ int c; c = (a+b)/2; a = 8; return c; } int main(void){ int a, b, c; a = 20; b = 12; c = avg(a, b); printf("%d\n", c); }
 
위 예시에서 함수에 따라 각각 다른 네임스페이스가 형성됨
→ 블록에 따라서 독립적인 변수 생성하는 것이 가능함
즉, 밑의 예시처럼 변수를 사용하는 것이 가능함
 
#include <stdio.h> int main(void){ int a, i; for (i=0; i<10; i++){ int b; b = 10; ... } ... if (a>10) { int b; b = 5; ... } }
 
근데 이럴 경우에는? 밑의 경우에는?
 
#include <stdio.h> int main(void){ int a, i; int b; ... for (i=0; i<10; i++){ int b; b = 10; #1 ... } b = 20; #3 if (a>10) { int b; b = 5; #2 ... } }
 
이 경우는 변수가 겹치게 되는 경우임
이 때는 가장 안쪽에 있는 변수로 인식함
 
 
내부 변수와 외부 변수
 

개념

 
블록 내부에서 선언한 변수는 내부 변수 (지역 변수)라고 부름
어떤 블록에도 속하지 않는 변수들을 외부 변수 (전역 변수)라고 부름
성질은 파이썬에서와 같음
 
notion image
 
위 사진 참고하기
 
내부 변수와 외부 변수의 차이
외부 변수는 프로그램이 생성될 때 한 번만 생성됨
내부 변수는 초기화 값을 지정하지 않으면 초기화 되지 않음 → 즉, 알 수 없는 값이 들어가 있는 상태인거임
이에 반해 외부 변수는 초기화 값을 지정하지 않으면 0을 저장함
++ 내부 변수는 블록이 끝나면 소멸되고, 외부 변수는 프로그램이 종료되면 소멸됨
 
notion image
 
#include <stdio.h> int call_cnt(void){ int cnt = 0; cnt ++; return cnt; } int main(void){ int i; for (i=0; i<10; i++){ printf("%d\n", call_cnt()); } }
 
여기서 1 2 3 4 .. 10 출력 되길 기대 → ????? 멍청이 아니야 당연히 아니지.. 저자가 바보임 ㄷㄷ
여기서 출력은 1 1 1 1 .. 이 될 것 → 초기화가 계속 되니까
 
#include <stdio.h> int cnt; int call_cnt(void){ cnt ++; return cnt; } int main(void){ int i; for (i=0; i<10; i++){ printf("%d\n", call_cnt()); } }
 
이렇게 바꾸면 저자가 기대했던 값 출력해줄 수 있음
아까 외부 변수는 초기화 해주지 않아도 된다고 했으므로 초기화 하지 않았음
 
#include <stdio.h> int cnt; # void는 return 값이 없는 함수를 의미 함 ! void call_cnt(void){ cnt ++; } int main(void){ int i; for (i=0; i<10; i++){ call_int(); printf("%d\n", cnt); } }
질문 : 함수도 return 값 안 쓸 수 있는데, 왜 굳이 void 씀? → main 함수만 return 값 안 쓸 수 있는건가..
 
외부 변수를 사용하면, (외부 변수는 어디 서든 사용 가능하니까) → 위와 같은 프로그램도 가능함
 
위와 같은 코드가 된다면 함수의 return 값 필요 없으니까 void를 이용하면 됨
 
내부 정적 변수
 

개념

 
외부 변수를 이용하면 ‘내부 변수와 외부 변수’ 파트에서도 확인할 수 있듯이
매개 변수를 사용하지 않아도 되고, 반환값도 필요 없어지게 됨 → 편의성 증가
 
그러나 이런 방법을 사용하면 프로그램이 길어질 때 디버깅 하기 힘듦
어디서 잘못 되었는지 찾기 힘드니까 !!
 
그래서 권장 되는 코딩 스타일은 “외부 변수를 사용하지 않는다” 임
 
그러나 가끔씩 외부 변수가 필요할 때도 있음
 
이 때 ‘내부 정적 변수’를 이용함
이는 블록 내부에서 생성되고, 내부에서 소멸되지만 프로그램이 끝날 때 까지 사라지지 않고 유지 되는 성질을 가지고 있음
 
#include <stdio.h> int call_cnt(void){ static int cnt; cnt; return cnt; } int main(void){ int i; for (i=0; i<10; i++){ printf("%d\n", call_cnt()); } }
 
내부 정적 변수는 앞에 static을 붙여주어서 정의 할 수 있음
 
notion image
내부 정적 변수의 성질
 
외부 정적 변수도 있지만 잘 쓰이진 않음 → 나중에 배울 예정
정적 변수는 보통 내부 정적 변수를 의미