[정보처리기사/예상문제] - 2024 정보처리기사 실기 예상 문제 모음
목차
1. 함수
2. 변수의 종류
3. 재귀 함수
4. 포인터
1. 함수
이처럼 함수는 특정 작업을 수행하는 코드의 집합이라고 생각하면 된다.
예를 들어 a+b라는 식이 있다고 생각하면 a+b가 한번만 나오면 상관없겠지만 엄청 많이 나오면 반복적인 작업임에도 코드가 길어지고 번거로울 수 있다. 그래서 더하기 작업을 수행하는 함수를 만들어 놓는 것이다.
함수의 기본 구조는 다음과 같다.
사진 출처 : C언어 - 함수의 구조, 함수의 형태 4가지 정리글 (1차 수정) : 네이버 블로그 (naver.com)
입력 형태에서 보이는 int x, int y는 매개 변수(Parameter)라고 한다.
함수의 형태는 아래 그림과 같이 4가지가 있다.
출력 형태가 있으면 1, 없으면 0
입력 형태가 있으면 1, 없으면 0
return의 의미는 반환하고 함수를 종료라는 의미이므로 출력 형태가 1인 경우에는 반드시 return문이 있어야 한다
사진 출처 : C언어 - 함수의 구조, 함수의 형태 4가지 정리글 (1차 수정) : 네이버 블로그 (naver.com)
함수를 배웠으니 변수의 종류에 대해 살펴보자.
2. 변수의 종류
함수에서 사용되는 변수는 지역 변수, 전역 변수, 정적(static) 변수, 외부(extern) 변수, 레지스터(register) 변수가 있다.
이 중에 지역 변수, 전역 변수, 정적(static) 변수만 공부해보도록 하자.
1) 지역 변수(Local Variable)
main() 함수, 조건문, 반복문의 중괄호({}) 내부와 함수의 매개 변수(Parameter)로 사용되는 변수를 의미한다
아래의 예문 출력결과가 무엇인지 예측 해보자.
#include<stdio.h>
int hello(void);
int main() {
int k = 20;
printf("%d\n",hello());
printf("%d", k);
return 0;
}
int hello(void) {
int k = 100;
return k;
}
100
20
#include<stdio.h>
int hello(void);
int main() {
int k = 20;
printf("%d\n",hello()); //100출력
printf("%d", k); //20 출력
return 0;
}
int hello(void) {
int k = 100;
return k;
}
위 예문을 보면 int k=20으로 초기화를 시킨후 hello라는 함수를 호출해서 k는 100이라고 바뀐줄 알았는데 그게 아니고 20이 그대로 호출되었다.
즉, main()함수의 k와 hello()함수의 k는 다르다는 것이다.
심도있게 알기 위해서는 메모리에 대해 알아야한다.
지역변수라서 함수가 종료되면 메모리 공간이 소멸된다.
2) 전역 변수(Global Variable)
중괄호 외부에 선언되는 변수로 어느 지역에서도 사용이 제한되지 않는 프로그램 어디에서든 접근이 가능한 변수이다
중괄호가 시작되면 메모리가 생성되고 해당 중괄호에서 빠져나오면 메모리가 소멸되는 지역변수와 달리 전역변수는 프로그램이 시작되면 메모리에 생성되고 프로그램이 종료되면 메모리가 소멸된다
그래서 전역 변수는 프로그램이 종료되지 않는 한 계속해서 메모리에 존재하고 영역에 제한받지 않으며 사용된다
그리고 전역 변수는 초깃값을 지정해주지 않아도 자동으로 값을 0으로 가진다.
전역 변수의 잘못된 사용과 남용은 공유 자원에 대한 잘못된 접근으로 부작용을 낳을 수 있는데 시스템의 변경과 유지 보수를 어렵게 하는 원인이 될 수있으므로 전역 변수의 사용은 최대한 피하는 것이 바람직하다
3) 정적 변수(Static)
전역 변수의 단점을 부분적으로 보완한 변수
정적변수는 변수의 자료형 앞에 static 키워드를 넣어서 만든다
static int a;
정적 변수는 전역 변수처럼 프로그램이 종료되지 않는 한 메모리가 소멸되지 않고 초깃값을 지정하지 않아도 자동으로 0으로 가지며 또한 정적 변수는 초기화가 단 1회만 수행된다.
다음 수행결과가 무엇일지 생각해보자.
#include<stdio.h>
void hello(void);
int main() {
int k = 20;
hello();
hello();
hello();
return 0;
}
void hello(void) {
static k = 1;
int t = 0;
k++;
t++;
printf("%d %d\n", k, t);
}
2 1
3 1
4 1
static 변수 k는 한번만 초기화되므로 k가 정상적으로 계속 증가하는 것을 볼 수 있지만
지역변수 t는 계속 초기화가 진행이 돼 모든 값이 1임을 확인할 수 있다.
3. 재귀함수(Recursive Function)
함수 내에서 자기 자신을 호출하는 함수
재귀 함수의 경우 계속적인 자기 자신의 함수 호출로 시간과 메모리 공간의 효율이 저하될 수 있다.
다음 코드의 결과값을 생각해보자.
#include<stdio.h>
int fact(int);
int main() {
int a=4;
printf("%d",fact(a));
return 0;
}
int fact(int n) {
if (n <= 1)
return 1;
else
return n * fact(n-1);
}
24
fact(4)=return 4 * fact(3)
fact(3)=return 3* fact(2)
fact(2)=return 2*fact(1)
fact(1)=1
fact(4)=4*3*2*1=24
따라서 결과는 24
위 문제는 재귀함수를 이용한 팩토리얼 예제였다.
4. 포인터
포인터(pointer)란 메모리의 주소값을 저장하는 변수이며, 포인터 변수라고도 부른다.
말 그대로 뭔가를 가리키는 의미를 가지고 있다. (주소값을 가리킴)
char형 변수가 문자를 저장하고, int형 변수가 정수를 저장하는 것처럼 포인터는 주소값을 저장한다.
포인터 변수의 선언은 아래와 같이 선언한다.
사진 출처 : C언어 포인터 사용시 주의점 : 네이버 블로그 (naver.com)
포인터 변수의 크기는 주소를 가리키기 때문에 항상 4byte의 동일한 크기를 가진다. (32bit 운영체제 한정)
1) 주소 연산자(&)
주소 연산자는 변수의 이름 앞에 사용하여, 해당 변수의 주소값을 반환한다.
2) 참조 연산자(*)
참조 연산자는 포인터의 이름이나 주소 앞에 사용하여, 포인터에 가리키는 주소에 저장된 값을 반환한다.
dereference라고 하여 역참조연산자라고도 한다.
다 필요없고 포인터는 하나만 알면 된다.
*p는 선언할 때를 제외하고 무조건 값을 가리킨다고 생각하면 되고 &는 주소를 가리킨다고 생각하면 된다.
아래는 대충 이해를 돕기위해 만든 표이다. (주소는 그냥 임시로 준 값이다)
#include <stdio.h>
int main() {
int a=3;
int b=&a;
int *c=&a;
printf("%d\n",a); //그냥 변수 a를 출력
printf("%d\n",b); //b에 저장된 a의 주소의 값을 출력
printf("%d\n",c); //포인터 변수 c에 저장된 a의 주소 출력
printf("%d\n",*c); //포인터 변수 c에 저장된 a의 주소의 값 출력
return 0;
}
printf("%d",a); //출력 결과 : 3
printf("%d",b); //출력 결과 : 1000K
printf("%d",c); //출력 결과 : 1000K
printf("%d",*c); //출력 결과 : 3
b는 a의 주소 값이 b라는 변수에 대입된 것이고
c는 a의 주소 값을 가리킬 수 있게 된 것이다
즉, a와 b는 연결고리가 없는 반면 a와 c는 연결고리가 있다.
3) 다차원 포인터
1차원 포인터에는 변수의 주소값이 저장되고 2차원포인터(이중포인터)에서는 1차원 포인터의 주소가 저장된다.
마찬가지로 3차원 포인터는 2차원 포인터의 주소가 저장된다
n차원 포인터는 n-1포인터의 주소를 넣는다.
#include <stdio.h>
int main() {
int a=3;
int* b=&a; //1차원 포인터 : 변수의 주소값 저장
int** c=&b; //2차원 보인터 : 1차원 포인터의 주소값 저장
printf("%d\n",b); //7행과 8행 동일
printf("%d\n",*c); // 결과값 : a의 주소
printf("%d\n",*b); //9행과 10행 동일
printf("%d\n",**c); //결과값 : 3
return 0;
}
포인터 변수 b는 a의 주소를 가리키기 때문에
b는 a의 주소이고
*b는 a의 값이다
포인터 변수 c는 b의 주소를 가리키기 때문에
c는 b의 주소이고
*c는 b의 값인데 b의 값이 a의 주소이므로 *c는 a의 주소이다.
*c가 a의 주소이므로 **c는 a의 주소의 값(즉, a의 값)이다
포인터 아무것도 이해 안돼도 좋다.
정보처리기사 실기는 어차피 결과값 묻는 문제가 대부분인데 포인터는 주소를 가리키는 녀석이다. 컴퓨터마다 메모리 주소가 다 다르므로 주소를 묻는 문제는 나올 수가 없다.
그래서 그냥 포인터변수가 나오면 상수 대입해서 대충 찍어봐라.
대부분 맞다.
아래는 기출문제이다. 한번 생각해보자.
#include <stdio.h>
int main(){
int *arr[3];
int a = 12, b = 24, c = 36;
arr[0] = &a;
arr[1] = &b;
arr[2] = &c;
printf("%d\n", *arr[1] + **arr + 1);
}
37
야매 풀이
*arr[1] 뭔지 모르겠는데 arr이 배열이니까 왠지 arr[1]=b의 값일 것 같다 =24
**arr 뭔지 모르겠지만 배열인데 아무것도 안적혀있는 거보니 arr[0]을 가리키는 것 같다 그러면 arr[0]+1하면 되지 않을까? =12+1
24+13=37
진짜 풀이
*arr[1]은 arr[1]의 값인데 arr[1]이 b의 주소를 가리키므로 b의 주소의 값(b의 값) = 24
arr은 배열의 이름이고 arr[0]의 주소와 동일한데 *arr은 a의 주소이고 **은 a의 주소의 값(a의 값) =12
24+12+1=37
(참고로 *가 우선순위 더 높아서 +1보다 먼저 수행된다)
4) 주소의 가감산
C언어에서 배우는 자료형은 모두 주소를 가지며 주소의 가감산이 가능하다.
char형 주소에 +1을 하면 1바이트 증가, int는 4바이트 증가, double은 8바이트 증가
다음은 기출문제이다. 출력결과를 예상해보자.
#include <stdio.h>
int main() {
char* p = "KOREA";
printf("%s\n", p);
printf("%s\n", p + 3);
printf("%c\n", *p);
printf("%c\n", *(p + 3));
printf("%c\n", *p + 2);
}
4번째 줄: KOREA라는 문자열의 주소를 포인터변수 p에 저장한다는 의미
5번째줄 : char이 p라는 주소에서 시작해서 널값 전까지를 전부 출력해서 KOREA
6번째줄 : char이 1byte이므로 +3하면 3칸이동한것이라고 생각하면 되는데 왼쪽으로 3칸이동해서 널값 전까지 전부 출력해서 EA
7번째줄 : 서식문자가 %c로 바뀌었고 p의 값을 물어보고 있으므로 K
8번째줄 : 서식문자가 %c로 바뀌었고 p+3(p에서 주소를 3칸 이동)의 값이므로 E
9번쨰줄 : 서식문자가 %c로 바뀌었고 p의 값에서 +2한 문자이므로 K,L,M 순이므로 M
그냥 p는 p의 제일 첫번째(p+0)를 가리키고 있다고 생각하면 됨
'정보처리기사 > 정처기 코딩 꿀팁' 카테고리의 다른 글
정보처리기사 실기-비전공자용 JAVA 요약 2탄(객체지향, 클래스) (0) | 2023.05.11 |
---|---|
정보처리기사 실기-비전공자용 Java 요약 1탄 (2) | 2023.05.10 |
정보처리기사 실기-비전공자용 C언어 요약 4탄(포인터 심화, 구조체) (8) | 2023.05.07 |
정보처리기사 실기-비전공자용 C언어 요약 2탄(조건문, 반복문, 배열) (4) | 2023.05.01 |
정보처리기사 실기-비전공자용 C언어 요약 1탄 (7) | 2023.04.29 |