Post

[2025년] 정보처리기사 실기 - C 언어

2025년도 1회, 2회, 3회의 정보처리기사 실기 기출문제 속 C 언어 문제를 정리하였다.

2025년 1회 정보처리기사 실기

문제 1. 문자의 ASCII 값

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
#include <stdio.h>

char Data[5] = {'B', 'A', 'D', 'E'};
char c;

int main() {
  int i, temp, temp2;

  c = 'C';
  printf("%d\n", Data[3] - Data[1]);

  for (i = 0; i < 5; ++i) {
    if (Data[i] > c)
      break;
  }

  temp = Data[i];
  Data[i] = c;
  i++;

  for (; i < 5; ++i) {
    temp2 = Data[i];
    Data[i] = temp;
    temp = temp2;
  }

  for (i = 0; i < 5; i++) {
    printf("%c", Data[i]);
  }
}
더보기

[정답]
4
BACDE

[풀이]
문자의 ASCII 값 : A=65, B=66, C=67, D=68, E=69

  • char Data[5] = {'B', 'A', 'D', 'E'};의 초기상태
1
2
3
4
5
6
7
Data[0] = 'B' (66)
Data[1] = 'A' (65)
Data[2] = 'D' (68)
Data[3] = 'E' (69)
Data[4] = '\0' (0) ← 배열 끝을 나타내는 null 문

c = 'C' (67)
1
printf("%d\n", Data[3] - Data[1]);

Data[3] = ‘E’ (69)
Data[1] = ‘A’ (65)
Data[3] - Data[1] = 69 - 65 = 4

printf("%d\n")이므로, 4를 출력 후, 줄바꿈을 한다.


1
2
3
4
for (i = 0; i < 5; ++i) {
  if (Data[i] > c)
    break;
}
1
2
3
i = 0; Data[0] = 'B' (66) > c = 'C' (67) ➔ false
i = 1; Data[1] = 'A' (65) > c = 'C' (67) ➔ false
i = 2; Data[2] = 'D' (68) > c = 'C' (67) ➔ true ➔ break; 실행

반복문에서의 break문을 만나면, 바로 그 반복문에서 빠져나온다.
따라서 i = 2에서 멈춘다.

1
2
3
temp = Data[i];
Data[i] = c;
i++;

temp = Data[i]; 여기서 i = 2이므로,
temp = Data[2] = ‘D’

Data[i] = c; c값은 ‘C’이므로,
Data[2] = ‘C’

i++이므로, i값은 3이 된다.

정리해보면 현재 배열은 아래와 같다.

1
2
3
Data = ['B', 'A', 'C', 'E', '\0']
temp = 'D'
i = 3


1
2
3
4
5
for (; i < 5; ++i) {
  temp2 = Data[i];
  Data[i] = temp;
  temp = temp2;
}

i = 3일때,
temp2 = Data[3] = ‘E’
Data[3] = temp = ‘D’
temp = temp2 = ‘E’

1
2
3
4
Data = ['B', 'A', 'C', 'D', '\0']
temp = 'E'
temp2 = 'E'
i = 3

i = 4일때,
temp2 = Data[4] = ‘\0’
Data[4] = temp = ‘E’
temp = temp2 = ‘\0’

1
2
3
4
Data = ['B', 'A', 'C', 'D', 'E']
temp = '\0'
temp = '\0'
i = 4

반복문 끝.


1
2
3
4
// 한글자씩 출력
for (i = 0; i < 5; i++) {
  printf("%c", Data[i]);
}

BACDE가 출력된다.

따라서 최종 답은 아래와 같다.

1
2
4
BACDE

C언어의 printf 함수는 기본적으로 출력 후 자동 줄바꿈을 하지 않는다.
따라서 줄바꿈을 하고 싶다면, 출력 내용 끝 부분에 \0을 작성해주어야 한다.


문제 2. 포인터 배열 동적 할당

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
32
#include <stdio.h>
#include <stdlib.h>

void set(int** arr, int* data, int rows, int cols) {
  for (int i = 0; i < rows * cols; ++i) {
    arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
  }
}

int main() {
  int rows = 3, cols = 3, sum = 0;
  int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9};
  int** arr;
  arr = (int**) malloc(sizeof(int*) * rows);
  for (int i = 0; i < cols; i++) {
    arr[i] = (int*) malloc(sizeof(int) * cols);
  }

  set(arr, data, rows, cols);

  for (int i = 0; i < rows * cols; i++) {
    sum += arr[i / rows][i % cols] * (i % 2 == 0 ? 1 : -1);
  }

  for (int i = 0; i < rows; i++) {
    free(arr[i]);
  }

  free(arr);

  printf("%d", sum);
}
더보기

[정답]
13

[풀이]
참고

  • malloc(sizeof(int*) * rows) : int 포인터 배열 동적 할당
  • free() : malloc으로 할당한 메모리 해제
1
2
3
4
5
6
7
8
9
10
int rows = 3, cols = 3, sum = 0;
int data[] = {5, 2, 7, 4, 1, 8, 3, 6, 9};
int** arr;

// rows 개수만큼 int 포인터 배열을 동적 할당
arr = (int**) malloc(sizeof(int*) * rows);
for (int i = 0; i < cols; i++) {
  // 각 포인터가 cols 개수만큼 int 배열을 가리키도록 생성
  arr[i] = (int*) malloc(sizeof(int) * cols);
}

메모리 구조는 아래와 같다.

1
2
3
4
5
arr
 ↓
[ptr0] → [int][int][int]
[ptr1] → [int][int][int]
[ptr2] → [int][int][int]


set(arr, data, rows, cols); 호출

1
2
3
4
5
void set(int** arr, int* data, int rows, int cols) {
  for (int i = 0; i < rows * cols; ++i) {
    arr[((i + 1) / rows) % rows][(i + 1) % cols] = data[i];
  }
}
idata[i](i + 1) / rows% rows(i + 1) % cols위치
05001arr[0][1] = 5
12002arr[0][2] = 2
27110arr[1][0] = 7
34111arr[1][1] = 4
41112arr[1][2] = 1
58220arr[2][0] = 8
63221arr[2][1] = 3
76222arr[2][2] = 6
89300arr[0][0] = 9

완성된 배열

1
2
3
arr[0] = {9, 5, 2}
arr[1] = {7, 4, 1}
arr[2] = {8, 3, 6}


1
2
3
for (int i = 0; i < rows * cols; i++) {
  sum += arr[i / rows][i % cols] * (i % 2 == 0 ? 1 : -1);
}
ii / rowsi % colsarr[i / rows][i % cols]i % 2 == 0sum
000arr[0][0] = 919
101arr[0][1] = 5-1-5
202arr[0][2] = 212
310arr[1][0] = 7-1-7
411arr[1][1] = 414
512arr[1][2] = 1-1-1
620arr[2][0] = 818
721arr[2][1] = 3-1-3
822arr[2][2] = 616

sum = 9 - 5 + 2 - 7 + 4 -1 + 8 -3 + 6
sum = 13

1
printf("%d", sum);

따라서 출력되는 결과는 13이다.


문제 3. 연결 리스트 (Linked List)

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
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <stdio.h>
#include <stdlib.h>

typedef struct Data {
  int value;
  struct Data* next;
} Data;

Data* insert(Data* head, int value) {
  Data* new_node = (Data*)malloc(sizeof(Data));
  new_node->value = value;
  new_node->next = head;
  return new_node;
}

Data* reconnect(Data* head, int value) {
  if (head == NULL || head->value == value) return head;

  Data* prev = NULL, *curr = head;
  while(curr != NULL && curr->value != value) {
    prev = curr;
    curr = curr->next;
  }

  if (curr != NULL && prev != NULL) {
    prev->next = curr->next;
    curr->next = head;
    head = curr;
  }
  return head;
}

int main() {
  Data* head = NULL, *curr;
  for(int i = 1; i <= 5; i++)
    head = insert(head, i);

  head = reconnect(head, 3);

  for (curr = head; curr != NULL; curr = curr->next)
    printf("%d", curr->value);

  return 0;
}
더보기

[정답]
35421

[풀이]
구조체 정의

1
2
3
4
typedef struct Data {
  int value;
  struct Data* next;
} Data;

연결 리스트(Linked List)의 노드를 정의한 것이다.

  • value : 노드의 값
  • next : 다음 노드를 가리키는 포인터


insert() 함수 - 맨 앞에 노드 추가

1
2
3
4
5
6
Data* insert(Data* head, int value) {
  Data* new_node = (Data*)malloc(sizeof(Data));
  new_node->value = value;
  new_node->next = head;
  return new_node;
}

새로운 노드를 생성한 뒤, 값을 넣고
기존 리스트의 맨 앞(head)에 삽입하는 함수이다.

1
2
for(int i = 1; i <= 5; i++)
  head = insert(head, i);
  • 실행 과정
1
2
3
4
5
i=1 -> 1 -> NULL
i=2 -> 2 -> 1 -> NULL
i=3 -> 3 -> 2 -> 1 -> NULL
i=4 -> 4 -> 3 -> 2 -> 1 -> NULL
i=5 -> 5 -> 4 -> 3 -> 2 -> 1 -> NULL
  • 최종 리스트
1
5->4->3->2->1


reconnect() 함수 - 특정 값을 가진 노드를 찾아 맨 앞으로 이동

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Data* reconnect(Data* head, int value) {
  // 예외 처리
  // 리스트가 비어있거나 이미 찾는 값이 맨 앞에 있는 경우 "그대로 반환"
  if (head == NULL || head->value == value) return head;

  // 노드 탐색 (curr = 현재 탐색 중인 노드, prev = curr의 이전 노드)
  Data* prev = NULL, *curr = head;
  while(curr != NULL && curr->value != value) {
    prev = curr;
    curr = curr->next;
  }

  // 위치 변경
  if (curr != NULL && prev != NULL) {
    prev->next = curr->next; // 기존 위치에서 제거 (->5->4->2->1)
    // 맨 앞으로 이동 (3->5->4->2->1)
    curr->next = head;
    head = curr;
  }
  return head;
}


최종 출력

1
2
3
4
5
6
7
8
9
10
11
12
int main() {
  Data* head = NULL, *curr;
  for(int i = 1; i <= 5; i++)
    head = insert(head, i); // 5->4->3->2->1

  head = reconnect(head, 3); // 3->5->4->2->1

  for (curr = head; curr != NULL; curr = curr->next)
    printf("%d", curr->value);

  return 0;
}

아래와 같이 띄어쓰기 없이 출력된다.

1
35421

연결 리스트(Linked List)

장점

  • 동적 크기 : 필요에 따라 크기 조절 가능
  • 삽입/삭제 용이 : 중간에 노드 추가/제거가 쉬움
  • 메모리 효율 : 필요한 만큼만 메모리 사용

단점

  • 순차 접근 : 특정 위치에 바로 접근 불가능
  • 추가 메모리 : 포인터 저장을 위한 추가 메모리가 필요
  • 캐시 효율성 : 데이터가 메모리에 연속적으로 저장되지 않음

문제 4. 16진수 ➔ 2진수, &(AND) 연산

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
#include <stdio.h>

typedef struct student {
  char* name;
  int score[3];
} Student;

int dec(int enc) {
  return enc & 0xA5;
}

int sum(Student* p) {
  return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}

int main() {
  Student s[2] = { "Kim", {0xA0, 0xA5, 0xDB}, "Lee", {0xA0, 0xED, 0x81} };
  Student* p = s;
  int result = 0;

  for (int i = 0; i < 2; i++) {
    result += sum(&s[i]);
  }

  printf("%d", result);
  return 0;
}
더보기

[정답]
908

[풀이]

1
2
3
  int dec(int enc) {
    return enc & 0xA5;
  }

& (AND 연산)

  • 두 비트가 모두 1일 때, 결과는 1이 된다.
    하나라도 0이면 결과는 0이 된다.
  • 0xA5가 특정 비트만 골라내는 역할이라고 보면 된다.

🤔 0xA5가 뭐야?
c언어에서 16진수를 표현할 때, 앞에 0x를 붙인다.

  • 숫자가 16개 필요하다.
1
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ➔ 총 16개
  • A = 10
  • A5 = (10 × 16^1) + (5 × 16^0)
    = 160 + 5
    = 165

165를 2진수로 바꾸면?
1010 0101이 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
dec 함수는 점수(enc)에 대해 0xA5와 AND 연산을 수행하여
특정 비트만 추출한 값을 반환한다.
*/
int dec(int enc) {
  return enc & 0xA5;
}

/*
sum 함수는 한 학생의 score 배열에 있는 3개의 값을 각각 dec() 함수로 처리한 후,
그 결과를 모두 더한 값을 반환한다.
*/
int sum(Student* p) {
  return dec(p->score[0]) + dec(p->score[1]) + dec(p->score[2]);
}

(1) Kim

1
{0xA0, 0xA5, 0xDB}
  • 0xA0
    • A = 1010
      0 = 0000
    • 1010 0000
1
2
3
4
  1010 0000  (0xA0)
& 1010 0101  (0xA5)
------------
  1010 0000 = 0xA0 = 160
  • 0xA5
    • 165
  • 0xDB
    • D = 1101
      B = 1011
    • 1101 1011
1
2
3
4
  1101 1011  (0xDB)
& 1010 0101  (0xA5)
------------
  1000 0001 = 0x81 = 129

총 합계
160 + 165 + 129 = 454

(2) Lee

1
{0xA0, 0xED, 0x81}
  • 0xA0
    • 160
  • 0xED
    • E = 1110
      D = 1101
    • 1110 1101
1
2
3
4
  1110 1101  (0xED)
& 1010 0101  (0xA5)
------------
  1010 0101 = 0xA5 = 165
  • 0x81
    • 8 = 1000
      1 = 0001
    • 1000 0001
1
2
3
4
  1000 0001  (0x81)
& 1010 0101  (0xA5)
------------
  1000 0001 = 0x81 = 129

총 합계
160 + 165 + 129 = 454

(최종 결과)
454 + 454 = 908


2025년 2회 정보처리기사 실기

문제 5. 원형 큐 (Circular Queue) 구현

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
#include <stdio.h>
#define SIZE 3

typedef struct {
  int a[SIZE];
  int front;
  int rear;
} Queue;

void enq(Queue* q, int val) {
  q->a[q->rear] = val;
  q->rear = (q->rear + 1) % SIZE;
}

int deq(Queue* q) {
  int val = q->a[q->front];
  q->front = (q->front + 1) % SIZE;
  return val;
}

int main() {
  Queue q = { {0}, 0, 0 };

  enq(&q,1); enq(&q,2); deq(&q); enq(&q,3);

  int first = deq(&q);
  int second = deq(&q);
  printf("%d 그리고 %d", first, second);

  return 0;
}
더보기

[정답]
2 그리고 3

[풀이]

1
2
3
4
5
  typedef struct {
    int a[SIZE];
    int front; // 꺼내는 위치
    int rear; // 넣는 위치
  } Queue;

Queue 자료구조 특징

  • FIFO (First In First Out)
  • 넣게 되면 뒤에 붙이고, 꺼내게 되면 앞에서 제거한다.
1
2
3
4
5
6
7
8
9
10
11
12
// 데이터 넣기
void enq(Queue* q, int val) {
  q->a[q->rear] = val;
  q->rear = (q->rear + 1) % SIZE;
}

// 데이터 꺼내기
int deq(Queue* q) {
  int val = q->a[q->front];
  q->front = (q->front + 1) % SIZE;
  return val;
}


1
2
3
4
5
6
7
8
9
10
11
int main() {
  Queue q = { {0}, 0, 0 };

  enq(&q,1); enq(&q,2); deq(&q); enq(&q,3);

  int first = deq(&q);
  int second = deq(&q);
  printf("%d 그리고 %d", first, second);

  return 0;
}
  • 초기 상태 (Queue q = { {0}, 0, 0 };)
index
00
10
20
1
2
front = 0
rear = 0
  • enq(&q, 1)
1
2
3
rear = 0
a[0] = 1
rear = (0 + 1) % 3 ⟹ 1
index
01
10
20
  • enq(&q, 2)
1
2
3
rear = 1
a[1] = 2
rear = (1 + 1) % 3 ⟹ 2
index
01
12
20
  • deq(&q)
1
2
val = a[front] ⟹ a[0] ⟹ 1
front = (0 + 1) % 3 ⟹ 1
  • enq(&q, 3)
1
2
a[2] = 3
rear = (2 + 1) % 3 ⟹ 0
index
01
12
23
  • int first = deq(&q); ⟹ 2
    • deq(&q) ⟹ 2
      • int val = a[1] ⟹ 2
      • front = (1 + 1) % 3 ⟹ 2
  • int second = deq(&q); ⟹ 3
    • deq(&q) ⟹ 3
      • int val = a[2] ⟹ 3
      • front = (2 + 1) % 3 ⟹ 0


1
printf("%d 그리고 %d", first, second);

현재 first 값과 second 값은 다음과 같다.
first = 2, second = 3

따라서 2 그리고 3이 출력된다.


문제 6. 이중 포인터 (Double Pointer)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

struct dat {
  int x;
  int y;
};

int main() {
  struct dat a[] = { {1,2}, {3,4}, {5,6} };
  struct dat* ptr = a;
  struct dat** pptr = &ptr;

  (*pptr)[1] = (*pptr)[2];
  printf("%d 그리고 %d", a[1].x, a[1].y);

  return 0;
}
더보기

[정답]
5 그리고 6

[풀이]

1
  struct dat a[] = { {1,2}, {3,4}, {5,6} };

배열 a 안에 구조체 3개가 들어있다.

indexxy
a[0]12
a[1]34
a[2]56
1
2
struct dat* ptr = a; // ptr = a[0]의 주소, ptr ➔ a[0]
struct dat** pptr = &ptr; // pptr ➔ ptr ➔ a[0]


1
(*pptr)[1] = (*pptr)[2];
1
2
3
4
5
6
7
*pptr = ptr

(*pptr)[1] = ptr[1] = a[1]
(*pptr)[2] = ptr[2] = a[2]

(*pptr)[1] = (*pptr)[2]
➔ a[1] = a[2] // 값이 복사되어 아래와 같이 바뀐다.
indexxy
a[0]12
a[1]56
a[2]56


1
printf("%d 그리고 %d", a[1].x, a[1].y);
1
2
a[1].x = 5
a[1].y = 6

따라서 5 그리고 6이 출력된다.


이중 포인터란,
포인터를 가리키는 포인터이다.

1
2
struct dat* ptr = a;   // ptr → a[0]
struct dat** pptr = &ptr; // pptr → ptr
1
pptr → ptr → a[0]

문제 7. node 구조체

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <stdlib.h>

struct node {
  int p;
  struct node* n;
};

int main() {
  struct node a = {1, NULL};
  struct node b = {2, NULL};
  struct node c = {3, NULL};

  a.n = &b; b.n = &c; c.n = NULL;
  c.n = &a; a.n = &b; b.n = NULL;

  struct node* head = &c;
  printf("%d %d %d", head->p, head->n->p, head->n->n->p);

  return 0;
}
더보기

[정답]
3 1 2

[풀이]
num_7_node

1
printf("%d %d %d", head->p, head->n->p, head->n->n->p);

따라서 3 1 2가 출력된다.


문제 8. 단일 연결 리스트 - head 삽입

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
#include <stdio.h>
#include <stlib.h>

struct node {
  char c;
  struct node* p;
};

struct node* func(char* s) {
  struct node* h = NULL, *n;
  while (*s) {
    n = malloc(sizeof(struct node));
    n->c = *s++;
    n->p = h;
    h = n;
  }
  return h;
}

int main() {
  struct node* n = func("BEST");

  while (n) {
    putchar(n->c);
    struct node* t = n;
    n = n->p;
    free(t);
  }
  return 0;
}
더보기

[정답]
TSEB

[풀이]

1
2
3
4
  struct node {
    char c; // 문자 저장
    struct node* p; // 다음 노드를 가리키는 포인터
  };
  • 새 노드가 항상 맨 앞에 삽입된다!
1
2
3
4
5
6
7
8
9
10
11
12
struct node* func(char* s) {
  struct node* h = NULL, *n;
  while (*s) {
    n = malloc(sizeof(struct node)); // 새 노드 동적 할당
    n->c = *s++;

    /* 아래 두 코드 ➔ 새 노드가 항상 맨 앞에 삽입되도록 함 */
    n->p = h; // 새 노드가 기존 리스트를 가리키게 함
    h = n; // 새 노드를 리스트의 시작(head)으로 변경
  }
  return h;
}


1
struct node* n = func("BEST");
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
32
33
34
35
36
37
38
39
40
41
42
43
(1) n = 1

n -> [? | ?]
n -> c = B, n -> [B | ?]
s++; ➔ E, s -> E
n -> p = NULL, n -> [B | NULL]
h = n = B
h -> B (head로 이동됨)

⟹ 현재 : h -> B -> NULL

(2) n = 2

n -> [? | ?]
n -> c = E, n -> [E | ?]
s++; ➔ S, s-> S
n -> p = h, h -> B이므로, n -> [E | B]
h = n = E
h -> E

⟹ 현재 : h -> E -> B -> NULL

(3) n = 3

n -> [? | ?]
n -> c = S, n -> [S | ?]
s++; ➔ T, s-> T
n -> p = h, h -> E이므로, n -> [S | E]
h = n = S
h -> S

⟹ 현재 : h -> S -> E -> B -> NULL

(4) n = 4

n -> [? | ?]
n -> c = T, n -> [T | ?]
s++; ➔ \0
n -> p = h, h -> S이므로, n -> [T | S]
h = n = T
h -> T

⟹ 현재 : h -> T -> S -> E -> B -> NULL

반환되는 리스트 : T -> S -> E -> B -> NULL


1
2
3
4
5
6
7
8
9
10
11
int main() {
  // ...

  while (n) {
    putchar(n->c); // 문자 하나를 출력하는 함수
    struct node* t = n;
    n = n->p; // 다음 노드로 이동
    free(t); // malloc으로 만든 메모리를 삭제하는 함수
  }
  return 0;
}

순회하며 문자열 출력하면 된다.
따라서 TSEB가 출력된다.


2025년 3회 정보처리기사 실기

문제 9. 문자열 포인터 연산

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

struct Test {
  int i;
  const char *g;
};

int main() {
  struct Test test[] = { {1, "AB"}, {2, "DC"}, {3, "EB"} };
  struct Test *p = &test[1];
  printf("%s", p->g + (p->i - 1));
  return 0;
}
더보기

[정답]
C

[풀이]

1
2
3
4
  struct Test {
    int i;
    const char *g; // 문자열의 시작 주소를 가리키는 포인터
  };
1
struct Test test[] = { {1, "AB"}, {2, "DC"}, {3, "EB"} };


1
2
3
struct Test *p = &test[1]; // test[1] = {2, "DC"}
// p->i = 2
// p->g = "DC"를 가리킴
1
printf("%s", p->g + (p->i - 1));
  • p->i - 1 = 2 - 1 = 1
  • p->g + 1
    • “DC”에서 한 칸 이동하여 “C”를 가리킴

%s는 해당 위치부터 문자열 끝(\0)까지 출력하므로
“C”가 출력된다.

따라서 출력 결과는 C이다.


문제 10. 후위연산, 전위연산

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main(void) {
  char str[] = "REPUBLICOFKOREA";
  int a = 0;
  while (str[a] != '\0')
    ++a;
  putchar(str[a-2]);
  return 0;
}
더보기

[정답]
E

[풀이]
먼저 짚고 가기
a++ (후위연산) : 현재 값을 사용 후 증가
++a (전위연산) : 먼저 증가 후 사용

Tip. 이 문제의 경우, 후위연산/전위연산 둘 다 최종 a = 15가 나온다.

1
2
while (str[a] != '\0')
  ++a;
str[a]a
str[0] = Ra = 1
str[1] = Ea = 2
str[2] = Pa = 3
str[3] = Ua = 4
str[4] = Ba = 5
str[5] = La = 6
str[6] = Ia = 7
str[7] = Ca = 8
str[8] = Oa = 9
str[9] = Fa = 10
str[10] = Ka = 11
str[11] = Oa = 12
str[12] = Ra = 13
str[13] = Ea = 14
str[14] = Aa = 15

str[15] = '\0'이므로, 반복문 종료


1
putchar(str[a-2]);

putchar() : 하나의 문자를 콘솔화면에 출력

  • str[a - 2]
    • str[15 - 2]
      = str[13]

따라서 str[13]은 “E”이므로,
“E” 가 최종적으로 출력된다.


문제 11. 비트 연산자 (XOR, OR, AND)

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
#include <stdio.h>

struct Node {
  struct Node* next;
  unsigned int x;
};

int main() {
  struct Node t1 = {0, 5u};
  struct Node t2 = {0, 7u};
  struct Node t3 = {0, 11u};

  t3.next = &t2;
  t2.next = &t1;

  struct Node* curr = &t3;
  int sum = 0;

  while (curr) {
    sum = sum * 3 + curr->x;
    curr = curr->next;
  }

  sum = (sum^42u) + 100u;
  printf("%u\n", sum);
}
더보기

[정답]
187

[풀이]

1
2
3
4
5
6
  struct Node {
    struct Node* next;
    // int의 범위를 양의 정수 범위로만 사용한 자료형 (unsigned int) ⟹ 음수 제외  
    // 0 ~ 4,294,967,295까지 표현함
    unsigned int x;
  };
1
2
t3.next = &t2;
t2.next = &t1;

t3 -> t2 -> t1 연결된다.


1
2
3
4
5
6
7
struct Node* curr = &t3;
int sum = 0;

while (curr) {
  sum = sum * 3 + curr->x;
  curr = curr->next;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
(1) &t3
sum = sum * 3 + curr->x;
sum = (0 * 3) + (11u) = 11u

curr = curr -> next;
curr = &t2
---------------------------
(2) &t2
sum = sum * 3 + curr->x;
sum = (11u * 3) + (7u)
= 33u + 7u = 40u

curr = curr -> next;
curr = &t1
---------------------------
(3) &t1
sum = sum * 3 + curr->x;
sum = (40u * 3) + (5u)
= 120u + 5u = 125u

curr = curr -> next;
curr = null


1
2
sum = (sum^42u) + 100u;
printf("%u\n", sum);

비트 연산자

  1. ^(XOR)
    두 비트가 다를 때는 1
    두 비트가 같으면 0
  2. | (OR)
    두 비트 중 하나만 1이면 ➔ 1
    두 비트 모두 0이면 ➔ 0
  3. & (AND)
    두 비트 모두 1이면 ➔ 1
    두 비트 중 하나라도 0이면 ➔ 0

이 문제에서는 ^(XOR) 비트 연산자를 사용하고 있다.
두 비트가 다를 때는 1, 두 비트가 같으면 0이다.

1
sum = (sum^42u) + 100u;

현재 sum값은 125u이다.

(125u^42u) + 100u

  • 125u (10진수인 125를 2진수로 바꿔야한다.)
1
2
3
4
5
6
7
8
125 ÷ 2 = 62 --- 1
62 ÷ 2 = 31 --- 0
31 ÷ 2 = 15 --- 1
15 ÷ 2 = 7 --- 1
7 ÷ 2 = 3 --- 1
3 ÷ 2 = 1 --- 1

1111101
  • 42u (10진수인 42를 2진수로 바꿔야한다.)
1
2
3
4
5
6
7
42 ÷ 2 = 21 --- 0
21 ÷ 2 = 10 --- 1
10 ÷ 2 = 5 --- 0
5 ÷ 2 = 2 --- 1
2 ÷ 2 = 1 --- 0

101010
  • 125u^42u

^(XOR) 비트 연산자 : 두 비트가 다를 때는 1, 두 비트가 같으면 0

1
2
3
4
  0111 1101
^ 0010 1010
------------
  0101 0111

0101 0111이 나온다.
이제 이 2진수 값을 10진수로 다시 바꾸면 된다.

1
2
3
4
5
6
0101 0111
= (2^7 * 0) + (2^6 * 1) + (2^5 * 0) + (2^4 * 1) + (2^3 * 0) + (2^2 * 1) + (2^1 * 1) + (2^0 * 1)
= 0 + 64 + 0 + 16 + 0 + 4 + 2 + 1
= 64 + 16 + 4 + 2 + 1
= 80 + 7
= 87

125u^42u 값은 87이다!

그럼 최종 sum값을 구해보자.
sum = (125u^42u) + 100u
= 87u + 100u
= 187u

따라서 최종 답은 187이다.


187u ← 여기서 u는 무엇일까?

u는 숫자를 unsigned int로 만들어주는 표시이다. (음수 제외)


문제 12. 비트 시프트 연산자

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>

int main() {
  int x = 7, y = 4, z;
  z = y % 3 < 3 ? 2 : 1;
  z = z & z >> 1;
  z = x > 5 && z <= 3 ? z * x : z / x;
  printf("%d", z);
  return 0;
}
더보기

[정답]
0

[풀이]

1
  int x = 7, y = 4, z; // 초기 변수
1
z = y % 3 < 3 ? 2 : 1; // z = 2
  • y % 3
    • 4 % 3 = 1
  • y % 3 < 3 ⟹ true
    • 2를 반환
1
z = z & z >> 1; // z = 0

» (비트 시프트 연산자) : 오른쪽으로 지정한 비트 수만큼 밀어준다.
& (비트 연산자) : 두 비트 모두 1이면 1, 하나라도 0이면 0

시프트 연산자가 비트 연산자보다 우선순위가 높다.

  • z » 1 부터 실행
    • z = 2 (2를 2진수로 바꾸면? 2진수 값 : 10)
    • 10을 오른쪽으로 1만큼 밀어주면, 01이 된다.
  • z & z » 1
1
2
3
4
  10
& 01
------------
  00 = (2^1 * 0 + 2^0 * 0) = 0 + 0 = 0

따라서 z값은 0이 된다.


1
z = x > 5 && z <= 3 ? z * x : z / x; // z = 0
  • x > 5 && z <= 3
    • x > 5 ⟹ x = 7 이므로 true 반환
    • z <= 3 ⟹ z = 0 이므로 true 반환
    • true && true이므로 true이다.
  • true에 해당하는 z * x를 실행
    • z * x0 * 7 ⟹ 0


1
printf("%d", z);

현재 z값인 0이 출력된다.


정리

printf함수

기본적으로 출력 후 자동 줄바꿈을 하지 않는다.
줄바꿈을 하고 싶다면, 출력 내용 끝 부분에 \0을 작성해주어야 한다.


비트 연산자 (XOR, AND, OR)

1. ^(XOR)

  • 두 비트가 다를 때는 1
    두 비트가 같으면 0

2. & (AND)

  • 두 비트가 모두 1이면 1
    두 비트 중 하나라도 0이면 0

3. | (OR)

  • 두 비트 중 하나만 1이면 1
    두 비트 모두 0이면 0

비트 시프트 연산자

  • >>
    • 오른쪽으로 지정한 비트 수만큼 밀어준다.
  • <<
    • 왼쪽으로 지정한 비트 수만큼 밀어준다.
1
z >> 1 // 오른쪽으로 1 만큼 밀어준다.


16진수

c언어에서 16진수를 표현할 때, 앞에 0x를 붙인다.
또한 16진수로 표현하기 위해선 숫자가 16개가 필요하다.

1
0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F ➔ 총 16개


printf() 주요 서식 지정자

서식 지정자는 printf(), scanf() 등의 함수에서 데이터의 자료형과 출력 및 입력 형식을 지정하는 역할을 한다.
(printf() : 출력 형식을 지정, scanf() : 입력 형식을 지정)

정수

서식 지정자자료형의미
%dint10진수 정수 출력
%iint10진수 정수 출력 (%d와 동일하게 동작)
%uunsigned int부호 없는 int 타입 정수 출력 (10진수)

문자/문자열

서식 지정자자료형의미
%cchar문자 하나 출력
%schar*, char[]문자열 출력 (\0까지)

[예시 코드]

1
2
3
4
5
6
7
8
9
10
printf("%d", 10); // 10

// u는 이 숫자를 unsigned int로 만드는 접미사이다.
// 따라서 10이 출력된다.
printf("%u", 10u); // 10

char *str = "ABC";

printf("%c", str[0]); // A
printf("%s", str); // ABC