배열, 문자열, 포인터, 구조체
C프로그래밍 학습 절입니다.
이번 절은 C에서 가장 중요하고 가장 헷갈리는 부분입니다.
이번 절의 핵심은 다음과 같습니다.
배열 = 같은 자료형 여러 개를 번호로 관리
문자열 = char 배열 + 끝 표시 '\0'
포인터 = 메모리 주소를 저장하는 변수
구조체 = 서로 다른 자료형을 하나로 묶는 방법이 내용은 C프로그래밍 출제범위의 배열, char형 배열과 문자열, 다차원 배열, 포인터, 포인터와 배열, 이중포인터, 구조체, 구조체 배열, 구조체 포인터, 공용체에 해당합니다. 또 배열과 포인터는 이후 자료구조의 배열, 순서리스트, 연결 리스트, 스택, 큐, 트리, 그래프와도 직접 연결됩니다.
이번 절의 큰 그림
지금까지 C에서 배운 것은 이 정도였습니다.
int a = 10;
float b = 3.14;
char c = 'A';이것은 변수 하나에 값 하나를 저장하는 방식입니다.
그런데 학생 100명의 점수를 저장해야 한다면?
int score1;
int score2;
int score3;
...
int score100;이렇게 하면 너무 불편합니다.
그래서 필요한 것이 배열입니다.
int score[100];이 한 줄이면 정수 100개를 저장할 수 있습니다.
그리고 포인터는 이 배열과 메모리를 이해하는 핵심 도구입니다.
int *p;구조체는 서로 다른 종류의 값을 하나로 묶습니다.
struct Student {
int id;
char name[20];
int score;
};즉 이번 절에서는 C에서 데이터를 크게 다루는 방법을 배웁니다.
배열
배열이란?
배열은 같은 자료형의 변수 여러 개를 하나의 이름으로 묶은 것입니다.
int score[5];이렇게 선언합니다.
score라는 이름으로 int형 공간 5개를 만듭니다.score[0] score[1] score[2] score[3] score[4]중요합니다.
C 배열의 번호는 0부터 시작합니다.
0, 1, 2, 3, 4입니다.
score[5]는 여섯 번째 칸이므로 범위를 벗어납니다.
배열 선언
배열 선언 형식은 다음과 같습니다.
자료형 배열이름[크기];int arr[5];
float height[10];
char name[20];| 코드 | 의미 |
|---|---|
int arr[5]; | 정수 5개 저장 |
float height[10]; | 실수 10개 저장 |
char name[20]; | 문자 20개 저장 |
배열의 각 칸을 배열 요소라고 합니다.
arr[0]
arr[1]
arr[2]이런 식으로 접근합니다.
배열에 값 넣기
int score[5];
score[0] = 90;
score[1] = 80;
score[2] = 70;
score[3] = 60;
score[4] = 50;이제 배열에는 이렇게 저장됩니다.
| 인덱스 | 값 |
|---|---|
score[0] | 90 |
score[1] | 80 |
score[2] | 70 |
score[3] | 60 |
score[4] | 50 |
출력은 이렇게 합니다.
printf("%d", score[0]);90배열 초기화
배열은 선언하면서 값을 바로 넣을 수 있습니다.
int score[5] = {90, 80, 70, 60, 50};이렇게 쓰면 다음과 같습니다.
| 인덱스 | 값 |
|---|---|
score[0] | 90 |
score[1] | 80 |
score[2] | 70 |
score[3] | 60 |
score[4] | 50 |
크기를 생략할 수도 있습니다.
int score[] = {90, 80, 70, 60, 50};이 경우 컴파일러가 값의 개수를 보고 크기를 5로 정합니다.
배열과 반복문
배열은 반복문과 같이 쓸 때 강력합니다.
int score[5] = {90, 80, 70, 60, 50};
int i;
for (i = 0; i < 5; i++) {
printf("%d ", score[i]);
}90 80 70 60 50i = 0; i < 5; i++입니다.
배열 크기가 5이므로 인덱스는 0부터 4까지입니다.
i < 5로 씁니다.
i <= 5라고 쓰면 score[5]까지 접근해서 위험합니다.
배열 예제: 합 구하기
#include <stdio.h>
int main(void) {
int score[5] = {90, 80, 70, 60, 50};
int i;
int sum = 0;
for (i = 0; i < 5; i++) {
sum += score[i];
}
printf("%d", sum);
return 0;
}sum = 0
sum += 90 → 90
sum += 80 → 170
sum += 70 → 240
sum += 60 → 300
sum += 50 → 350350시험 예시형 배열 문제
네 C프로그래밍 자료에도 배열과 반복문이 결합된 문제가 나옵니다.
#include <stdio.h>
int moon[] = {1,2,3,4,5,6,7,8,9,10};
void main(void)
{
int a, sum = 0;
for (a = 0; a < 8; ++a)
if (moon[a] % 2 == 0)
sum += moon[a];
printf("%d", sum);
}여기서 핵심은 세 가지입니다.
a는 0부터 7까지 변합니다.
moon[0]부터 moon[7]까지만 봅니다.
그중 짝수만 더합니다.배열 값은 다음과 같습니다.
| a | moon[a] |
|---|---|
| 0 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 5 |
| 5 | 6 |
| 6 | 7 |
| 7 | 8 |
2, 4, 6, 82 + 4 + 6 + 8 = 2020이 문제는 배열 인덱스가 0부터 시작한다는 점을 모르면 틀리기 쉽습니다.
배열에서 가장 흔한 실수
실수 1: 인덱스 범위 초과
int arr[5];
arr[5] = 10; // 잘못된 접근arr[5]는 존재하지 않습니다.
배열 크기가 5이면 마지막 인덱스는 4다.
arr[0], arr[1], arr[2], arr[3], arr[4]실수 2: 초기화하지 않은 배열 값 사용
int arr[5];
printf("%d", arr[0]);초기화하지 않은 배열에는 쓰레기값이 들어 있을 수 있습니다.
가능하면 초기화하자.
int arr[5] = {0};이렇게 하면 모든 요소가 0으로 초기화됩니다.
다차원 배열
배열은 한 줄짜리만 있는 것이 아닙니다.
표처럼 행과 열을 가진 배열도 만들 수 있습니다.
int matrix[2][3];2행 3열짜리 정수 배열그림은 다음과 같습니다.
| 0열 | 1열 | 2열 | |
|---|---|---|---|
| 0행 | matrix[0][0] | matrix[0][1] | matrix[0][2] |
| 1행 | matrix[1][0] | matrix[1][1] | matrix[1][2] |
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};printf("%d", matrix[1][2]);matrix[1][2]는 1행 2열입니다.
62차원 배열과 반복문
2차원 배열은 보통 중첩 반복문으로 처리합니다.
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};
int i, j;
for (i = 0; i < 2; i++) {
for (j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("\n");
}1 2 3
4 5 6i = 행
j = 열이라고 보면 됩니다.
자료구조에서도 배열은 행렬 표현, 희소 행렬, 전치 행렬에서 중요하게 사용됩니다.
문자열
문자열이란?
이제 문자열로 넘어갑니다.
C에는 사실 Java나 Python처럼 별도의 문자열 자료형이 없습니다.
char 배열입니다.
문자 하나는 이렇게 저장했습니다.
char ch = 'A';문자열은 문자 여러 개입니다.
char name[6] = "KIM";이때 실제 저장은 이렇게 됩니다.
| 인덱스 | 값 |
|---|---|
name[0] | 'K' |
name[1] | 'I' |
name[2] | 'M' |
name[3] | '\0' |
name[4] | 사용 안 함 |
name[5] | 사용 안 함 |
여기서 '\0'이 중요합니다.
문자열 끝 표시 '\0'
C 문자열은 끝을 표시하기 위해 널 문자 '\0'을 사용합니다.
문자열 = 문자들 + '\0'char str[] = "ABC";실제 저장은 다음과 같습니다.
| 인덱스 | 값 |
|---|---|
str[0] | 'A' |
str[1] | 'B' |
str[2] | 'C' |
str[3] | '\0' |
그래서 "ABC"는 글자 3개지만, 저장 공간은 최소 4칸이 필요합니다.
A, B, C, \0중요합니다.
문자열 배열 크기는 글자 수보다 1칸 더 필요합니다.
문자와 문자열 차이
이것은 시험에서 자주 헷갈리기 쉽습니다.
| 구분 | 예 | 의미 |
|---|---|---|
| 문자 | 'A' | 문자 하나 |
| 문자열 | "A" | 문자 A와 끝 표시 '\0' |
'A'와 "A"는 다릅니다.
char ch = 'A';
char str[] = "A";ch는 문자 하나입니다.
str은 배열이고 실제로는:
'A', '\0'이 저장됩니다.
문자열 출력
문자열 출력은 %s를 사용합니다.
#include <stdio.h>
int main(void) {
char name[] = "KIM";
printf("%s", name);
return 0;
}KIM문자 하나 출력은 %c입니다.
printf("%c", name[0]);K문자열 입력
문자열 입력도 %s를 사용합니다.
char name[20];
scanf("%s", name);여기서 name 앞에는 보통 &를 붙이지 않습니다.
scanf("%s", name);이렇게 씁니다.
왜냐하면 배열 이름 name 자체가 배열의 시작 주소처럼 사용되기 때문입니다.
이것은 포인터에서 바로 이어서 설명합니다.
scanf("%s", name);은 공백 전까지만 입력받습니다.
Kim Sanghoon이면 name에는 Kim만 들어갑니다.
문자열 함수
문자열을 다룰 때는 string.h에 있는 함수를 자주 씁니다.
#include <string.h>대표 함수는 다음과 같습니다.
| 함수 | 의미 |
|---|---|
strlen | 문자열 길이 |
strcpy | 문자열 복사 |
strcat | 문자열 이어붙이기 |
strcmp | 문자열 비교 |
#include <stdio.h>
#include <string.h>
int main(void) {
char str[] = "ABC";
printf("%d", strlen(str));
return 0;
}3strlen은 '\0'을 제외한 실제 글자 수를 셉니다.
sizeof와 strlen 차이
char str[10] = "ABC";sizeof(str)은 배열 전체 크기입니다.
10strlen(str)은 문자열 길입니다.
3정리하면 다음과 같습니다.
| 표현 | 결과 | 의미 |
|---|---|---|
sizeof(str) | 10 | 배열 전체 크기 |
strlen(str) | 3 | 문자열 실제 길이 |
이 차이는 중요합니다.
포인터
포인터란?
이제 C에서 가장 중요한 포인터입니다.
포인터는 메모리 주소를 저장하는 변수입니다.
변수는 메모리에 저장됩니다.
int a = 10;이렇게 쓰면 메모리 어딘가에 a라는 공간이 생기고, 그 안에 10이 들어갑니다.
그 공간에는 주소가 있습니다.
a의 주소 = 1000번지
a의 값 = 10포인터는 이 주소를 저장합니다.
int *p;
p = &a;p는 int형 변수의 주소를 저장하는 포인터입니다.
p에는 a의 주소가 들어갑니다.주소 연산자 &
&는 변수의 주소를 구하는 연산자입니다.
int a = 10;
printf("%p", &a);&a는 a의 주소입니다.
&a = a가 메모리에서 어디에 있는지입니다.
2장 1절에서 scanf를 배울 때 이렇게 썼습니다.
scanf("%d", &a);그 이유는 scanf가 입력값을 a에 직접 넣으려면 a의 주소를 알아야 하기 때문입니다.
간접 참조 연산자 *
포인터 앞에 *를 붙이면, 그 주소에 있는 값을 의미합니다.
int a = 10;
int *p;
p = &a;
printf("%d", *p);10p = a의 주소
*p = p가 가리키는 곳의 값 = a의 값 = 10이기 때문입니다.
정리하면 다음과 같습니다.
| 표현 | 의미 |
|---|---|
a | 변수 a의 값 |
&a | 변수 a의 주소 |
p | p에 저장된 주소 |
*p | p가 가리키는 주소에 있는 값 |
포인터 예제
#include <stdio.h>
int main(void) {
int a = 10;
int *p;
p = &a;
printf("%d\n", a);
printf("%d\n", *p);
*p = 20;
printf("%d\n", a);
return 0;
}a = 10
p = &a
*p는 a를 의미
*p = 20은 a = 20과 같은 효과10
10
20중요합니다.
*p를 바꾸면 p가 가리키는 원본 변수의 값이 바뀝니다.포인터 선언 읽는 법
int *p;이것은 이렇게 읽습니다.
p는 int형 변수를 가리키는 포인터입니다.char *cp;
float *fp;
double *dp;| 선언 | 의미 |
|---|---|
int *p; | int형 주소 저장 |
char *cp; | char형 주소 저장 |
float *fp; | float형 주소 저장 |
double *dp; | double형 주소 저장 |
int* p;
int *p;둘 다 같은 뜻입니다.
하지만 여러 개 선언할 때는 조심해야 합니다.
int* p, q;이것은 p만 포인터고, q는 일반 int 변수입니다.
int *p, *q;라고 쓰는 것이 좋습니다.
포인터와 함수
2장 3절에서 C는 기본적으로 값에 의한 전달이라고 했습니다.
void change(int x) {
x = 100;
}이렇게 하면 원본이 바뀌지 않습니다.
하지만 포인터를 쓰면 원본을 바꿀 수 있습니다.
#include <stdio.h>
void change(int *p) {
*p = 100;
}
int main(void) {
int a = 10;
change(&a);
printf("%d", a);
return 0;
}100change(&a)로 a의 주소를 넘김
p는 a의 주소를 받음
*p = 100은 a = 100과 같은 효과포인터와 배열의 관계
C에서 배열 이름은 배열의 시작 주소처럼 사용됩니다.
int arr[3] = {10, 20, 30};arr은 보통 arr[0]의 주소처럼 동작합니다.
arr == &arr[0]라고 이해하면 됩니다.
int *p;
p = arr;이 코드는 가능합니다.
왜냐하면 arr이 배열의 시작 주소이기 때문입니다.
배열을 포인터로 접근하기
int arr[3] = {10, 20, 30};
int *p = arr;이때는 다음과 같습니다.
| 표현 | 값 |
|---|---|
arr[0] | 10 |
arr[1] | 20 |
arr[2] | 30 |
*p | 10 |
*(p + 1) | 20 |
*(p + 2) | 30 |
arr[i] == *(arr + i)입니다.
printf("%d", *(p + 1));20포인터 연산
포인터에 1을 더하면 주소가 진짜 숫자 1만큼 증가하는 것이 아닙니다.
자료형 크기만큼 이동합니다.
int arr[3] = {10, 20, 30};
int *p = arr;int가 4바이트라고 하면:
p → arr[0]
p + 1 → arr[1]
p + 2 → arr[2]즉 포인터 연산은 배열 요소 단위로 이동합니다.
*(p + 1)은 두 번째 요소입니다.
배열을 함수에 넘기기
배열을 함수에 넘기면 실제로는 배열의 시작 주소가 전달됩니다.
void printArray(int arr[], int size) {
int i;
for (i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
}int data[3] = {10, 20, 30};
printArray(data, 3);10 20 30배열을 함수에 넘기면 함수 안에서 원본 배열 값을 바꿀 수 있습니다.void changeFirst(int arr[]) {
arr[0] = 100;
}이 함수는 원본 배열의 첫 번째 값을 바꿉니다.
이중 포인터
이중 포인터는 포인터의 주소를 저장하는 포인터입니다.
int **pp;int a = 10;
int *p = &a;
int **pp = &p;| 표현 | 의미 |
|---|---|
a | 값 10 |
&a | a의 주소 |
p | a의 주소 |
*p | a의 값 |
pp | p의 주소 |
*pp | p, 즉 a의 주소 |
**pp | a의 값 |
printf("%d", **pp);10이중 포인터는 처음에는 어렵습니다. 지금은 이렇게만 기억해도 됩니다.
포인터 = 변수의 주소 저장
이중 포인터 = 포인터 변수의 주소 저장구조체와 공용체
구조체란?
이제 구조체로 넘어갑니다.
배열은 같은 자료형 여러 개를 묶습니다.
int score[5];하지만 학생 한 명의 정보를 저장하려면 자료형이 다릅니다.
학번: int
이름: char 배열
점수: int
학점: char이것을 따로따로 관리하면 불편합니다.
int id;
char name[20];
int score;
char grade;학생이 100명이면 더 복잡해집니다.
그래서 구조체를 씁니다.
구조체는 서로 다른 자료형을 하나로 묶어서 처리하는 사용자 정의 자료형입니다.
C프로그래밍 예시문제에서도 구조체는 “서로 다른 종류의 자료를 하나로 묶어서 처리하기 위한 것”이라는 설명이 나옵니다.
구조체 선언
구조체는 이렇게 만듭니다.
struct Student {
int id;
char name[20];
int score;
};이것은 Student라는 구조체 틀을 만든 것입니다.
아직 실제 학생 변수가 만들어진 것은 아닙니다.
실제 변수는 이렇게 만듭니다.
struct Student s1;이제 s1은 학생 한 명의 정보를 담을 수 있습니다.
구조체 멤버 접근
구조체 안의 각 항목을 멤버라고 합니다.
struct Student {
int id;
char name[20];
int score;
};id, name, score입니다.
구조체 변수의 멤버에 접근할 때는 점 .을 씁니다.
s1.id = 2024001;
s1.score = 90;문자열은 배열이므로 strcpy를 쓰는 경우가 많습니다.
strcpy(s1.name, "Kim");#include <stdio.h>
#include <string.h>
struct Student {
int id;
char name[20];
int score;
};
int main(void) {
struct Student s1;
s1.id = 2024001;
strcpy(s1.name, "Kim");
s1.score = 90;
printf("%d %s %d", s1.id, s1.name, s1.score);
return 0;
}2024001 Kim 90구조체 초기화
구조체는 선언과 동시에 초기화할 수도 있습니다.
struct Student s1 = {2024001, "Kim", 90};이렇게 하면 순서대로 들어갑니다.
| 멤버 | 값 |
|---|---|
id | 2024001 |
name | "Kim" |
score | 90 |
구조체 배열
학생이 여러 명이면 구조체 배열을 씁니다.
struct Student students[3] = {
{1, "Kim", 90},
{2, "Lee", 80},
{3, "Park", 70}
};printf("%s", students[0].name);Kimint i;
for (i = 0; i < 3; i++) {
printf("%d %s %d\n",
students[i].id,
students[i].name,
students[i].score);
}1 Kim 90
2 Lee 80
3 Park 70구조체 배열은 실제 프로그램에서 매우 많이 씁니다.
학생 목록
회원 목록
상품 목록
게시글 목록이런 것들이 전부 구조체 배열로 표현될 수 있습니다.
구조체 포인터
구조체도 포인터로 가리킬 수 있습니다.
struct Student s1 = {1, "Kim", 90};
struct Student *p;
p = &s1;이제 p는 s1의 주소를 저장합니다.
구조체 포인터로 멤버에 접근할 때는 두 가지 방법이 있습니다.
(*p).scorep->score둘은 같은 뜻입니다.
p->score == (*p).score보통은 ->를 많이 씁니다.
printf("%d", p->score);90구조체를 함수에 전달하기
구조체도 함수에 넘길 수 있습니다.
값으로 전달
void printStudent(struct Student s) {
printf("%d %s %d", s.id, s.name, s.score);
}이 방식은 구조체 전체가 복사됩니다.
구조체가 크면 비효율적일 수 있습니다.
포인터로 전달
void printStudent(struct Student *p) {
printf("%d %s %d", p->id, p->name, p->score);
}printStudent(&s1);포인터로 넘기면 복사 비용이 줄고, 함수 안에서 원본을 바꿀 수도 있습니다.
typedef와 구조체
구조체 이름을 매번 이렇게 쓰면 깁니다.
struct Student s1;그래서 typedef를 자주 씁니다.
typedef struct Student {
int id;
char name[20];
int score;
} Student;이제 이렇게 쓸 수 있습니다.
Student s1;더 간단해집니다.
C프로그래밍 예시문제에서도 구조체 정의 시 typedef와 같이 사용할 수 있다고 나옵니다.
구조체 태그명은 반드시 필요할까요?
구조체는 태그명을 생략할 수도 있습니다.
typedef struct {
int id;
char name[20];
int score;
} Student;여기에는 struct Student 같은 태그명이 없습니다.
그래도 Student라는 이름으로 사용할 수 있습니다.
구조체 태그명은 반드시 있어야 하는 것은 아닙니다.C프로그래밍 예시문제에서도 “구조체 정의 시 태그명은 반드시 있어야 합니다”가 잘못된 설명으로 제시됩니다.
공용체란?
공용체는 union으로 만듭니다.
구조체와 비슷하게 여러 멤버를 가지지만, 중요한 차이가 있습니다.
union Data {
int i;
float f;
char c;
};구조체는 멤버들이 각각 따로 공간을 가집니다.
공용체는 멤버들이 같은 메모리 공간을 공유합니다.
| 구분 | 구조체 struct | 공용체 union |
|---|---|---|
| 메모리 사용 | 멤버들이 각각 공간 차지 | 모든 멤버가 같은 공간 공유 |
| 동시에 저장 | 여러 멤버 값 유지 가능 | 보통 하나의 값만 의미 있게 유지 |
| 크기 | 멤버 크기의 합에 가까움 | 가장 큰 멤버 크기 기준 |
| 목적 | 서로 다른 정보를 묶음 | 같은 공간을 여러 방식으로 해석 |
union Data d;
d.i = 10;
d.f = 3.14;이렇게 하면 d.i와 d.f가 같은 공간을 공유하므로, 마지막에 저장한 f 때문에 i의 값은 의미가 깨질 수 있습니다.
처음에는 이렇게만 기억하자.
struct = 여러 값을 함께 저장
union = 한 공간을 여러 멤버가 공유개념 연결 정리
배열, 포인터, 구조체가 자료구조로 이어지는 방식
이번 절에서 배운 내용은 다음 자료구조 단원과 바로 연결됩니다.
| C 개념 | 자료구조 연결 |
|---|---|
| 배열 | 순서리스트, 스택, 큐의 기본 구현 |
| 포인터 | 연결리스트, 트리, 그래프 구현 |
| 구조체 | 노드 표현 |
| 구조체 포인터 | 노드 연결 |
| 동적 메모리 | 필요할 때 노드 생성 |
예를 들어 연결리스트의 노드는 보통 구조체로 만듭니다.
struct Node {
int data;
struct Node *next;
};data = 실제 값
next = 다음 노드의 주소즉 구조체와 포인터가 합쳐지면 연결리스트가 됩니다.
자료구조 범위에도 연결 리스트에서 노드, 포인터, 링크, 노드 삽입, 노드 삭제를 다룹니다.
이번 절에서 배운 개념을 한 번에 연결하기
학생 3명의 정보를 저장한다고 가정해 보겠습니다.
학번, 이름, 점수를 가집니다.
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[20];
int score;
} Student;
int main(void) {
Student students[3] = {
{1, "Kim", 90},
{2, "Lee", 80},
{3, "Park", 70}
};
int i;
int sum = 0;
for (i = 0; i < 3; i++) {
sum += students[i].score;
}
printf("sum = %d\n", sum);
return 0;
}여기에는 이번 절 내용이 다 들어 있습니다.
| 코드 | 개념 |
|---|---|
typedef struct | 구조체 |
char name[20] | 문자열 배열 |
Student students[3] | 구조체 배열 |
students[i].score | 구조체 멤버 접근 |
for | 반복문 |
sum += | 누적합 |
sum = 240자주 혼동되는 출제 포인트
혼동 포인트 1. 배열 인덱스는 0부터 시작합니다
int arr[5];0, 1, 2, 3, 4arr[5]는 범위 밖입니다.
혼동 포인트 2. for (i = 0; i < 8; i++)
이것은 8번 반복합니다.
i = 0, 1, 2, 3, 4, 5, 6, 7i = 8은 실행하지 않습니다.
혼동 포인트 3. 문자열에는 '\0'이 필요합니다
char str[] = "ABC";'A', 'B', 'C', '\0'입니다.
혼동 포인트 4. 문자와 문자열은 다릅니다
'A' // 문자
"A" // 문자열혼동 포인트 5. scanf("%s", name)에는 보통 &를 붙이지 않습니다
char name[20];
scanf("%s", name);배열 이름이 시작 주소처럼 쓰이기 때문입니다.
혼동 포인트 6. 포인터에서 &와 *를 구분해야 합니다
| 기호 | 의미 |
|---|---|
&a | a의 주소 |
*p | p가 가리키는 곳의 값 |
혼동 포인트 7. 배열 이름은 시작 주소처럼 쓰입니다
arr == &arr[0]라고 이해하면 됩니다.
혼동 포인트 8. 구조체 일반 변수는 . 사용
s1.score구조체 포인터는 -> 사용.
p->score혼동 포인트 9. 구조체 태그명은 반드시 필요한 것이 아닙니다
typedef struct { ... } Student;처럼 태그명을 생략할 수 있습니다.
혼동 포인트 10. 구조체와 공용체 차이
struct = 멤버들이 각자 공간
union = 멤버들이 같은 공간 공유이번 절의 핵심 정리
배열
int arr[5] = {1, 2, 3, 4, 5};arr[0]부터 arr[4]까지 사용2차원 배열
int matrix[2][3] = {
{1, 2, 3},
{4, 5, 6}
};문자열
char str[] = "ABC";'A', 'B', 'C', '\0'포인터
int a = 10;
int *p = &a;&a = a의 주소
p = a의 주소
*p = a의 값배열과 포인터
arr == &arr[0]
arr[i] == *(arr + i)구조체
struct Student {
int id;
char name[20];
int score;
};구조체 멤버 접근
s1.score구조체 포인터 접근
p->score공용체
union Data {
int i;
float f;
char c;
};모든 멤버가 같은 메모리 공간 공유핵심 한 문장
이번 절의 핵심을 한 문장으로 정리하면 다음과 같습니다.
배열은 같은 자료형을 연속적으로 저장하고, 문자열은 char 배열로 표현되며, 포인터는 메모리 주소를 다루고, 구조체는 서로 다른 자료형을 하나로 묶어서 복잡한 데이터를 표현합니다.
배열 = 같은 것 여러 개
문자열 = char 배열 + '\0'
포인터 = 주소
구조체 = 다른 것들을 한 묶음확인 문제
문제 1
다음 배열에서 마지막 요소의 인덱스는?
int arr[5];① 3 ② 4 ③ 5 ④ 6
문제 2
다음 코드의 출력 결과는?
int arr[3] = {10, 20, 30};
printf("%d", arr[1]);① 10 ② 20 ③ 30 ④ 오류
문제 3
다음 코드의 출력 결과는?
int moon[] = {1,2,3,4,5,6,7,8,9,10};
int a, sum = 0;
for (a = 0; a < 8; ++a)
if (moon[a] % 2 == 0)
sum += moon[a];
printf("%d", sum);① 12 ② 16 ③ 20 ④ 30
문제 4
C 문자열의 끝을 나타내는 문자는?
① '\n'
② '\0'
③ '0'
④ "0"
문제 5
다음 중 문자 하나를 나타내는 것은?
① "A"
② 'A'
③ ABC
④ {A}
문제 6
다음 코드에서 &a의 의미는?
int a = 10;① a의 값 ② a의 주소 ③ a의 자료형 ④ a의 크기
문제 7
다음 코드의 출력 결과는?
int a = 10;
int *p = &a;
printf("%d", *p);① 0 ② 10 ③ a의 주소 ④ 오류
문제 8
다음 코드 실행 후 a의 값은?
int a = 10;
int *p = &a;
*p = 20;① 10 ② 20 ③ 주소값 ④ 알 수 없음
문제 9
배열과 포인터의 관계로 알맞은 것은?
① 배열 이름은 항상 배열의 마지막 주소입니다 ② 배열 이름은 배열의 시작 주소처럼 사용됩니다 ③ 배열은 포인터와 전혀 관련이 없습니다 ④ 배열 인덱스는 1부터 시작합니다
문제 10
서로 다른 자료형을 하나로 묶기 위해 사용하는 것은?
① 배열 ② 포인터 ③ 구조체 ④ 반복문
문제 11
구조체 변수 s1의 멤버 score에 접근하는 올바른 표현은?
① s1->score
② s1.score
③ s1:score
④ s1#score
문제 12
구조체 포인터 p가 가리키는 구조체의 score 멤버에 접근하는 올바른 표현은?
① p.score
② p->score
③ p#score
④ p:score
정답과 해설은 절별 확인문제 정답해설에서 확인합니다.
다음 3장 1절은 자료구조 개념, 시간복잡도, 배열입니다. 이제 C 문법을 바탕으로 “데이터를 어떻게 효율적으로 저장하고 처리할 것인가”로 넘어갑니다.