이전에 제가 네이버 블로그에 쓴 글을 가져와 일부 내용을 추가하였습니다. ⇒ https://blog.naver.com/racoo_oon/222434455079
구조체
C언어의 경우 한 배열에는 같은 자료형의 데이터들만 저장할 수 있다. 다양한 타입의 데이터를 묶기 위해서는 구조체가 필요하다.
C언어에서는 struct 키워드를 이용해 표기하고 형식은 다음과 같다.
struct student {
char name[10];
int age;
double gpa;
};
책에 있는 예시를 그대로 들고 왔다. 구조체에 저장되는 항목은 문자열인 이름, 정수형인 나이, 실수형인 학점이다.
struct 뒤의 student는 구조체들을 서로 구분해주는 구조체 태그라고 한다.
위의 코드는 형식만 지정해 준 것이고 실제로 구조체 변수를 정의하려면 다음과 같이 하면 된다.
struct student smj;
당연히도 구조체 정의는 메인함수 밖에서, 변수선언은 메인함수 안에서 한다.
구조체 안의 항목들에 값을 저장해보겠다.
struct student smj;
strcpy(smj.name, "minjee seo");
smj.age = 23;
smj.gpa = 4.3;
학점은 내 희망사항,,
위의 예시처럼 멤버 연산자 ( . ) 를 이용하면 구조체 내의 항목 (멤버) 에 접근이 가능하다.
책에서는 주로 typedef를 이용해 구조체를 정의하고 있는데 이렇게 할 경우 선언한 구조체는 새로운 데이터 타입이 된다.
맨 처음 예시와 동일한 구조체를 typedef를 이용해 정의해보면 아래와 같다.
typedef struct {
char name[10];
int age;
double gpa;
} student;
이 경우 student라는 새로운 데이터 타입이 생성된 것이므로 타입 이름만으로 변수 선언이 가능하다.
또한 중괄호를 사용하여 초기화할 수 있다.
student smj;
student smj = { "minjee seo", 23, 4.3 };
책에 있는 퀴즈 문제인 2차원 좌표 공간에서 하나의 점을 나타내는 구조체 point를 정의하고 구조체 변수 p1, p2를 선언한 후 각각 (1,2) , (9,8)로 초기화한 다음 두 개의 구조체 변수를 받아서 점 사이의 거리를 계산하는 함수 get_distance(point p1, point p2)를 작성하는 문제를 풀어보겠다. (한번에 쓰려니까 길다..)
#include <stdio.h>
#include <math.h>
typedef struct {
int x;
int y;
} point;
double get_distance(point p1, point p2) {
double x_d, y_d;
x_d = (p1.x - p2.x);
y_d = (p1.y - p2.y);
return (sqrt((x_d)*(x_d) + (y_d)*(y_d)));
}
int main() {
point p1 = { 1,2 };
point p2 = { 9,8 };
printf("distance : %f\n", get_distance(p1, p2));
}
포인터
포인터는 다른 변수의 주소를 가지고 있는 변수이다.
변수 선언 시 변수가 메모리 공간에 저장되는데 이 때 메모리의 각 바이트에는 주소가 매겨져 있다. 포인터에는 이 주소가 저장된다.
이해를 위해 우선 정수형 변수 a를 선언한 뒤 100으로 초기화하고 포인터 변수도 선언해보자.
int a = 100;
int* p; //포인터 변수는 이렇게 선언함.
포인터 p가 a를 가리키게 하려면 a의 주소를 추출해 p에 대입하면 된다. 추출은 & 연산자로 한다.
p = &a;
이제 p가 가리키는 곳에 값을 새로 저장해보겠다. 저장은 * 연산자로 한다.
*p = 200;
a를 출력해보면 a의 값이 200으로 바뀐 것을 확인할 수 있을 것이다.
아무것도 가리키고 있지 않은 포인터는 널 포인터라고 한다. 포인터에 주소를 지정하지 않았을 때는 항상 널 포인터 상태로 만들어 두는 것이 좋은데 잘못된 포인터로 메모리를 변경하면 치명적인 결과가 발생할 수 있기 때문이다 (...) 변수를 초기화하지 않을 시 변수에는 쓰레기 값이 저장되기 때문에 당장 사용하지 않는 포인터는 널 포인터로 만들어 두자.
함수의 매개변수로 포인터를 사용하면 함수 외부의 변수를 변경할 수 있다.
간단하게 외부 변수의 값을 100으로 바꾸는 함수를 작성해보겠다.
void change_val(int *p) {
*p = 100;
}
int main() {
int num = 10;
printf("value : %d\n", num);
change_val(&num);
printf("value : %d\n", num);
}
함수의 매개변수로 함수 외부 변수의 주소를 추출해 넘겨 주면 함수 안에서 해당 주소의 값을 바꿔 준다.
또한 포인터를 통해 구조체 멤버에 접근할 때에는 다음과 같이 보다 편리한 표기법을 사용할 수 있다.
(*p).member; // 원래 표기법
p->member; // 편리한 표기법
배열과 포인터
배열의 이름은 배열의 시작 위치 (주소) 를 가리키는 포인터이다. 배열의 이름에 공간이 할당되지는 않지만 배열의 이름이 있는 곳이 배열의 첫 번째 요소의 주소로 대치되기 때문에 배열이 함수로 전달될 때 실제로는 포인터가 전달된다고 할 수 있다.
따라서 함수로 배열이 전달되면 함수 내부에서 배열의 내용을 변경할 수 있다.
함수 안에서 배열의 내용을 변경하는 간단한 함수를 구현해보자.
#include <stdio.h>
#define SIZE 5 // 편의상 배열의 크기를 미리 정의한다.
// 리스트의 요소를 0으로 초기화하는 함수
void list_to_zero(int list[])
{
for (int i = 0; i < SIZE; i++) {
list[i] = 0;
}
}
// 리스트의 요소를 출력하는 함수
void printList(int list[]) {
for (int i = 0; i < SIZE; i++) {
printf("%d", list[i]);
}
printf("\n");
}
int main(void) {
int mylist[SIZE] = {1, 2, 3, 4, 5};
printList(mylist);
list_to_zero(mylist);
printList(mylist);
}
출력도 다음과 같이 잘 되는 것을 확인할 수 있다.
12345
00000
동적 메모리 할당
필요한 만큼의 메모리를 운영체제로부터 할당받아 사용하고 사용이 끝나면 반납하는 기능이다.
이 떄 동적 메모리가 할당되는, 운영체제가 사용하지 않는 메모리 공간을 모아 놓은 곳을 히프라고 한다.
포인터로만 사용할 수 있다!
int* p;
p = (int*)malloc(sizeof(int));
*p = 100;
free(p);
먼저 malloc()함수를 이용해 변수의 크기 (여기서는 int) 만큼의 메모리 블록을 할당하고 동적 메모리 블럭의 시작 주소를 반환해 포인터에 저장한다.
포인터를 이용해 할당된 메모리에 변수를 저장한 후 free()함수를 이용하면 메모리를 다시 반환할 수 있다.
이때 malloc 함수가 반환했던 포인터 값을 잊어버리면 동적 메모리를 반환할 수 없다!
또한 malloc이 반환한 값이 NULL이 아닌지 항상 검사해야 한다. (메모리를 할당할 수 없으면 NULL을 반환하기 때문)
구조체와 포인터
구조체에 대한 포인터를 선언하고 포인터를 통해 구조체 멤버에 접근해 보자. 이 때 동적 메모리 할당을 이용해 구조체를 생성한다.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
typedef struct myProfile {
char name[10];
int age;
char major[SIZE];
}me;
int main(void) {
me *m; // 구조체 me를 가리키는 포인터
m = (me*)malloc((sizeof(me))); // 구조체 사이즈만큼의 동적 메모리를 할당하고 m에 주소 저장
strcpy(m->name, "Minjee");
m->age = 24;
strcpy(m->major, "MBE");
free(m); // 동적 메모리 사용이 끝나면 꼭 free해주자
}
'Computer Science > DataStructure' 카테고리의 다른 글
[자료구조] C언어로 쉽게 풀어쓴 자료구조 : 6장 연결 리스트 Ⅰ (0) | 2022.04.13 |
---|---|
[자료구조] C언어로 쉽게 풀어쓴 자료구조 : 3장 연습문제 (0) | 2022.04.12 |