✔️ 배열
같은 자료형의 변수들이 연속된 메모리 공간을 차지하는 자료구조
인덱스와 인덱스에 대응하는 데이터들로 이루어진 자료구조이다.
int arr[5]; // 배열 선언
arr[0] = 10; // 0번째 인덱스에 접근하여 값을 바꿈, set 연산
int value = arr[0] // 0번째 인덱스에 접근하여 값을 가져옴, get 연산
int arr[] = {1, 2, 3, 4}; // 배열 바로 초기화

1차원 배열 : base(주소값) + n * sizeof(자료형)
2차원 배열 : base(주소값) + (i * 열의 개수 + j )* sizeof(자료형) // i : 행, j : 열
이러한 형식으로 실질적인 배열 인덱스에 접근한다.
응용 : 행렬 (matrix)
2차원 배열을 이용하여 배열의 전체 요소를 저장하는 방법
장점 : 행렬의 연산들을 간단하게 구현 가능
단점 : 희소 행렬의 경우 많은 메모리 공간 낭비
희소 행렬 : 대부분의 항들이 0인 행렬

0이 아닌 요소들만 저장하는 방법
장점 : 희소 행렬의 경우, 메모리 공간의 절약
단점 : 각종 행렬 연산들의 구현이 복잡

✔️ 구조체
하나 이상의 변수를 묶어 그룹화하는 사용자 정의 자료형
- 동일한 타입의 구조체는 대입이 가능
- 함수의 매개변수로 전달 할 때 구조체는 그대로 전달하면 복사된다.
- 그러나 배열은 시작주소만 전달될 뿐이다.
// 구조체 선언
struct Friend {
char name[16]; // 문자배열
int age; // 나이
};
// 구조체 변수 생성
struct Friend friend1; // 바로 값을 초기화 가능
// 값 초기화
strcpy(friend1.name, "길동무");
friendA.age = 12;
typedef를 사용하여 구조체의 형식을 정의할 수 있다.
// 구조체 선언
typedef struct {
char str[16];
int age;
} Friend;
// 구조체 변수 생성
Friend friend1 = { "홍길동", 12 };
배열과 구조체의 차이점
배열 : 자료형이 같은 데이터들의 묶음
구조체 : 자료형이 다른 데이터들의 묶음
대입이 가능
다음 코드는 초기화된 구조체 Friend를 구현한 friend1에 값을 초기화하고 friend2 에 대입후 friend2에서 age 값을 15로 바꿨을 때 if 조건문에서 True라면 구조체의 참조값을 대입한 것이고, 서로 다르다면 대입시 friend1의 값을 그대로 대입했다고 볼 수 있다.
#include <stdio.h>
#include <string.h>
typedef struct {
char name[16];
int age;
} Friend;
int main() {
Friend friend1 = { "홍길동", 12 };
Friend friend2 = friend1;
friend2.age = 15;
if (strcmp(friend1.name, friend2.name) == 0 && friend1.age == friend2.age) {
printf("구조체 대입시 참조값을 가진다.\n");
}
else {
printf("구조체 대입시 값이 그대로 대입된다.\n");
}
return 0;
}
결과

✔️ 포인터
다른 변수의 주소를 가지는 변수
포인터 연산자 : *
포인터가 가리키는 내용

char a = 'A';
char *p; // char형 포인터
p = &a; // 주소값을 전달

❓ 궁금증
p = a; 하면 어떻게 될까 ?

포인터는 a변수의 실질적인 값 그 자체를 가리키게 된다.
a = 'A' 이고 'A'는 메모리에서 41번째에 있다. 즉, 'A'라는 문자 값 자체를 가리키게된 것이다.
참고 : 'A' 는 ASCII 에서 65 이지만 메모리 주소는 16진수로 표현되기 때문에 4 x 16^1 + 1x16^0 이므로 65이다.
배열에서 포인터
배열의 이름이 사실상 포인터와 같은 역할이다
int arr[] = { 1,2,3 };
printf("%d\n", *arr);
// 출력결과
// 1
for (int i = 0; i < sizeof(arr) / sizeof(int); i++) {
printf("%d ", *(arr + i));
}
// 출력 결과
// 1 2 3
//sacnf를 사용하여 배열에 값 넣기
scanf_s("%d", &arr[0]);
✔️ 동적 메모리 할당 / 반납
프로그램 실행 도중 메모리를 할당 받는 것
필요한 만큼 할당받고 필요한 때에 사용하고 반납
메모리를 매우 효율적으로 사용가능
동적할당
1. 메모리에서 Heap 영역에 할당한다.
2. 할당시 포인터를 사용하여 할당한다.
// 동적 할당
int *p;
p = (int *)malloc(크기 * sizeof(int));
// 2차원 배열 할당
int *p = calloc(n*m, sizeof(int)); // 1차원 각 요소들
int **pp = malloc(n*sizeof(int)); // 2차원 n행
for (int i = 0; i < n; i++) {
pp[i] = p + i*m; // 요소 + i번째 행 * 열크기
// 이 경우 행 x 열을 하면 pp[0] 은 p + 0, pp[1] = 1*m이 된다.
// 즉, 한 배열 열에서 열 개수만큼 잘라서 행을 구성한다.
}
// 반납
free(p);
// 일반화
(자료형 *)malloc(크기 * sizeof(자료형));
🔖 참고자료
- C로 쉽게 풀어쓴 자료구조 - 생능출판사
'CS > 자료구조' 카테고리의 다른 글
연결리스트 (0) | 2024.07.09 |
---|---|
큐(queue)와 덱(deque) (0) | 2024.07.02 |
스택 (Stack) (0) | 2024.07.01 |
순환 (0) | 2024.01.26 |
자료구조의 정의 (0) | 2024.01.26 |