| #include <stdio.h> int f(int *a) { static int b=0; (*a)++; b=b+2; return b; } int main() { int x=0, y=0; x = f(&y); y = y + f(&x); printf("%d", x+y); } |
정적 변수 b가 호출 사이에 값을 유지하므로 x+y의 값은 8이다.
첫 호출 f(&y)에서 y는 1이 되고 b는 2가 되어 2를 반환하므로 x = 2이다.
둘째 호출 f(&x)에서 x는 3이 되고 static 변수 b는 이전 값을 이어받아 4가 되어 4를 반환한다.
따라서 이고, 출력은 이다.
| C 언어로 작성한 프로그램(“A”라고 칭함)과 스크립트 언어(예: shell script)로 작성한 프로그램(“B”라고 칭함)은 실행파일 형태로 만들어진 후 실행될 때 그 실행 방식에 차이가 있다. A의 경우 실행파일이 기계어를 담고 있으므로 메모리에 직접 로드(load) 되어 실행되는 반면 B의 경우 실행파일에 기계어가 아닌 텍스트 파일이 저장돼 있으므로 직접 실행되지 못하고 [ ]가 먼저 실행되면서 B의 내용을 한 줄씩 해석하며 실행한다. |
빈칸에 들어갈 용어는 인터프리터(Interpreter)이다.
스크립트 파일은 기계어가 아닌 텍스트이므로, 인터프리터가 먼저 실행되어 내용을 한 줄씩 해석하며 실행한다.
- 컴파일러: 소스 코드 전체를 미리 기계어로 번역하는 프로그램으로, 실행 시점에 한 줄씩 해석하지 않는다.
- 링커: 목적 파일과 라이브러리를 연결해 실행 파일을 만드는 프로그램이다.
- 로더: 실행 파일을 메모리에 적재하는 프로그램으로, 내용을 해석하지 않는다.
옳지 않은 것은 소지기반 인증을 지식 비교로 설명한 내용이다.
인증자와 검증자가 아는 지식을 비교하는 방식은 지식기반 인증이고, 소지기반은 스마트카드·OTP 토큰처럼 가진 물건으로 인증한다.
- 인증기술을 사용자·메시지·디바이스 인증으로 구분하는 설명은 옳다.
- 전자인증서가 사용자의 신원과 문서 내용을 보증한다는 설명은 옳다.
- 생체인식 기반이 신체적 특성을 이용한다는 설명은 옳다.
문맥 교환이 반드시 발생하는 경우는 라운드 로빈에서 할당시간이 만료된 때이다.
대기 큐에 프로세스가 있는 상태에서 시간 할당량이 끝나면 실행 중인 프로세스는 CPU를 내놓고 대기 큐의 다음 프로세스로 교체된다.
- I/O 완료 인터럽트: 인터럽트 처리 후 중단됐던 프로세스가 그대로 실행을 이어갈 수 있다.
- 시스템콜: 사용자 모드에서 커널 모드로 전환될 뿐, 처리가 끝나면 같은 프로세스가 계속 실행될 수 있다.
- 쓰레드의 I/O 요청: 논블로킹 방식이면 호출한 쓰레드가 실행을 이어갈 수 있어 교체가 필수는 아니다.
| #include <stdio.h> int main(int argc, char *argv[]) { FILE *z = fopen(argv[2], "w"); fprintf(z, "hello"); fclose(z); } |
생성되는 파일의 이름은 y이다.
명령행 인자 배열에서 argv[0]은 프로그램 이름, argv[1]은 x, argv[2]는 y이므로 fopen은 y라는 파일을 쓰기 모드로 연다.
- w: 파일 이름이 아니라 쓰기 모드를 뜻하는 문자열이다.
- x: argv[1]의 값으로, fopen에 전달되지 않는다.
- z: 파일 포인터 변수의 이름일 뿐 파일 이름과 무관하다.
옳지 않은 것은 회귀 테스트를 모듈 회귀와 증분적 회귀로 나눈 설명이다.
회귀 테스트는 변경으로 인한 부작용을 확인하려고 기존 테스트를 다시 수행하는 것으로, 일반적으로 재수행 범위에 따라 전체 회귀 테스트와 선택적 회귀 테스트로 나눈다.
- 명세 기반 테스트가 블랙박스 테스트이며 신택스·동등 분할·경계 값 분석 기법을 쓴다는 설명은 옳다.
- 순환복잡도를 지역 수로 구하든 분기 수로 구하든 결과가 같다는 설명은 옳다.
- 통합 테스트가 단위 테스트를 마친 모듈의 통합 과정에서 생기는 오류를 찾는다는 설명은 옳다.
옳지 않은 것은 개념적 데이터 모델의 데이터 구조가 저장 모습을 표현한다는 설명이다.
데이터를 어떤 모습으로 저장할지 표현하는 것은 논리적 데이터 모델의 데이터 구조이고, 개념적 데이터 모델의 데이터 구조는 현실 세계를 추상화한 개체와 개체 간의 관계를 표현한다.
- 데이터 모델이 데이터 구조·연산·제약조건으로 구성된다는 설명은 옳다.
- 논리적 데이터 모델링이 개념 세계의 데이터를 데이터베이스에 저장할 구조로 표현하는 작업이라는 설명은 옳다.
- 제약조건에 구조적 측면과 연산 적용 시의 의미적 측면이 있다는 설명은 옳다.
설명에 해당하는 것은 RAID 2이다.
RAID 2는 해밍 코드 같은 오류교정코드를 별도 디스크에 저장해, 오류 검출 기능이 없는 디스크의 오류를 찾아 복구한다.
- RAID 1: 같은 데이터를 다른 디스크에 그대로 복제하는 미러링 방식이다.
- RAID 3: 바이트 단위로 나눈 데이터의 패리티를 전용 디스크에 저장한다.
- RAID 5: 블록 단위 패리티를 모든 디스크에 분산 저장한다.
파일 A의 소유자에게는 읽기와 실행 권한만 있고 쓰기 권한은 없다.
chmod 531에서 소유자 자리의 숫자 5는 이진수 101, 곧 r-x이다.
이어지는 chmod go-x는 그룹(g)과 기타 사용자(o)의 실행 권한만 제거하므로 소유자 권한은 r-x 그대로 유지된다.
| def cals(nums): if nums == 1 : return 1 else: return nums * cals(nums-1) in_value = 4 result = cals(in_value) print(result) |
cals는 재귀로 팩토리얼을 구하는 함수이므로 출력은 24이다.
nums가 1이면 1을 반환하고, 그 외에는 nums * cals(nums-1)을 반환한다.
호출을 펼치면 cals(4) = 4 * cals(3) = 4 * 3 * cals(2) = 4 * 3 * 2 * cals(1)이다.
옳지 않은 것은 세마포어의 p연산을 signal 동작으로 설명한 내용이다.
p연산은 임계 영역에 들어가기 전 수행하는 wait 동작이고, 대기 중인 프로세스를 깨우며 임계 영역에서 나올 때 수행하는 signal 동작은 v연산이다.
- 임계 영역 문제의 해결 조건이 상호배제·진행·제한된 대기라는 설명은 옳다.
- 검사와 지정을 원자적으로 수행하는 명령처럼 하드웨어적 해결 방법이 있다는 설명은 옳다.
- 모니터가 공유자원을 숨기고 인터페이스만 제공해 동기화한다는 설명은 옳다.
옳지 않은 것은 쓰레드 지원에 운영체제의 지원이 필수적이라는 설명이다.
쓰레드는 운영체제가 모르더라도 사용자 수준 쓰레드 라이브러리만으로 구현할 수 있다.
- 같은 프로세스의 쓰레드들이 가상 메모리를 공유한다는 설명은 옳다.
- 프로세스의 주소 공간이 스와핑되면 그에 속한 쓰레드 전부가 함께 스와핑된다는 설명은 옳다.
- 멀티코어에서 쓰레드를 병렬 처리해 성능을 높일 수 있다는 설명은 옳다.
옳지 않은 것은 하둡을 빅데이터 분석 기술로 든 설명이다.
텍스트 마이닝과 군집분석은 분석 기술이지만, 하둡은 대용량 데이터를 분산 저장·처리하는 프레임워크이다.
- DIKW 계층구조가 데이터에서 지혜로 발전하는 과정을 나타낸다는 설명은 옳다.
- 빅데이터의 3V가 다양성·속도·양이라는 설명은 옳다.
- 키-값 데이터베이스가 NoSQL의 가장 단순한 형태라는 설명은 옳다.
설명에 해당하는 성질은 고립성(Isolation)이다.
고립성은 수행 중인 트랜잭션의 중간 결과에 다른 트랜잭션이 접근하지 못하게 하는 성질이다.
- 원자성: 트랜잭션의 연산이 모두 반영되거나 전혀 반영되지 않아야 한다는 성질이다.
- 일관성: 트랜잭션 수행 후에도 데이터베이스가 일관된 상태를 유지해야 한다는 성질이다.
- 지속성: 완료된 트랜잭션의 결과가 영구히 보존되어야 한다는 성질이다.
옳지 않은 것은 스왑 영역에서 메모리로 가져오는 작업을 스왑아웃이라 한 설명이다.
스왑 영역에서 메모리로 가져오는 작업은 스왑인이고, 메모리에서 스왑 영역으로 내보내는 작업이 스왑아웃이다.
- 메모리 오버레이가 큰 프로그램을 적당한 크기로 잘라 가져오는 기법이라는 설명은 옳다.
- 메모리 분할방식을 가변분할과 고정분할로 구분한다는 설명은 옳다.
- 프로세스 크기에 맞춰 할당하는 가변분할방식을 세그먼테이션이라 한다는 설명은 옳다.
가상 머신을 사용하는 이유로 옳지 않은 것은 서버의 성능 증가이다.
가상화는 물리적 자원을 나누어 쓰고 가상화 계층의 부담까지 더해지므로, 서버 자체의 성능을 높이지는 못하며 자원 활용과 관리의 효율을 높이는 기술이다.
- 서로 다른 운영체제용 응용 프로그램을 한 서버에서 실행할 수 있다는 점은 사용 이유에 해당한다.
- 한 물리적 서버에서 여러 가상 머신을 실행할 수 있다는 점은 사용 이유에 해당한다.
- 물리적 서버를 새로 구축하는 것보다 설치 시간이 짧다는 점은 사용 이유에 해당한다.
| * + a b c |
주어진 식을 후위표기로 바꾼 결과는 a b + c *이다.
전위식 * + a b c는 연산자 *의 왼쪽 피연산자가 + a b, 오른쪽 피연산자가 c이므로 중위식으로 (a + b) * c이다.
- a b c * +: 중위식 a + (b * c)에 해당해 연산 순서가 다르다.
- a + b * c: 연산자가 피연산자 사이에 있는 중위표기이다.
- a b * c +: 중위식 (a * b) + c에 해당해 연산자가 뒤바뀌어 있다.
올바른 구문은 UPDATE 테이블_이름 SET 속성이름1 = 값1, 속성이름2 = 값2;이다.
UPDATE 문은 수정할 테이블을 지정한 뒤 SET 절에 속성과 새 값을 나열한다.
- UPDATE INTO … SELECT: INTO와 SELECT를 쓰는 것은 INSERT 문의 형식이다.
- UPDATE FROM … WHERE: FROM 뒤에 조건만 두는 것은 DELETE 문의 형식이며 새 값을 지정하는 SET 절이 없다.
- UPDATE … VALUES: VALUES는 INSERT 문에서 쓰는 절이다.
옳지 않은 것은 속성의 전체 개수를 카디널리티라 한 설명이다.
카디널리티는 릴레이션의 튜플 개수이고, 속성의 전체 개수는 차수(degree)이다.
- 릴레이션 스키마가 릴레이션 이름과 속성 이름을 정의한 논리적 구조라는 설명은 옳다.
- 릴레이션에 튜플의 유일성과 속성의 무순서 특성이 있다는 설명은 옳다.
- 속성의 원자성이 속성값으로 원자값만 허용한다는 뜻이라는 설명은 옳다.
| int a[4][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; |
a[2][1]의 값은 8이다.
C 언어의 2차원 배열은 행 우선으로 초기화되므로 3개씩 끊으면 a[0]은 {1, 2, 3}, a[1]은 {4, 5, 6}, a[2]는 {7, 8, 9}, a[3]은 {10, 11, 12}이고, a[2][1]은 a[2]의 두 번째 원소이다.
- 2: a[0][1]의 값이다.
- 3: a[0][2]의 값이다.
- 7: a[2][0]의 값으로, 같은 행의 첫 번째 원소이다.
해당 용어는 탐색시간(seek time)이다.
탐색시간은 헤드가 원하는 트랙(실린더)까지 이동하는 시간이다.
- 회전지연시간: 원하는 섹터가 회전해 헤드 아래에 올 때까지 기다리는 시간이다.
- 전송시간: 데이터를 실제로 읽거나 쓰는 데 걸리는 시간이다.
- 접근시간: 헤드 이동과 회전 대기 등을 합친, 데이터에 접근하기까지의 전체 시간이다.
설명에 해당하는 기술은 NAT이다.
NAT(Network Address Translation)는 내부의 사설 IP 주소를 공인 IP 주소로 변환해 여러 컴퓨터가 하나의 인터넷 연결을 공유하게 한다.
- DHCP: 단말에 IP 주소 등 네트워크 설정을 자동으로 할당하는 프로토콜이다.
- DNS: 도메인 이름을 IP 주소로 변환하는 시스템이다.
- SMTP: 전자우편을 전송하는 프로토콜이다.
비정형 방법에 해당하지 않는 것은 모형검증기법이다.
모형검증기법은 시스템을 수학적 모형으로 표현해 성질을 검증하는 정형 방법이다.
- 개별검토: 사람이 산출물을 직접 읽고 검토하는 비정형 방법이다.
- 소프트웨어검사: 정해진 절차에 따라 사람이 결함을 찾는 비정형 방법이다.
- 검토회의: 여러 사람이 모여 산출물을 함께 검토하는 비정형 방법이다.
TCP 기반 프로토콜이 아닌 것은 DNS이다.
DNS의 일반적인 질의·응답은 연결 설정 없이 빠르게 주고받는 UDP를 사용한다.
- HTTP: 웹 문서를 신뢰성 있게 전달하기 위해 TCP를 사용한다.
- FTP: 제어와 데이터 전송 연결 모두 TCP를 사용한다.
- SMTP: 메일 전달의 신뢰성을 위해 TCP를 사용한다.
인터프리터에 해당하지 않는 것은 자바 컴파일러이다.
자바 컴파일러는 소스 코드를 실행하지 않고 바이트코드로 번역하는 번역기이다.
- 자바 가상 머신: 바이트코드를 해석해 실행하는 인터프리터 역할을 한다.
- 파이썬 인터프리터: 파이썬 코드를 해석해 실행한다.
- PHP 인터프리터: PHP 코드를 해석해 실행한다.