포인터 한 학기 동안 안썼더니 또 까먹어버렸다...
자료구조에 관한 과목 수강하다가, 기초 지식인 포인터를 확실히 알아야겠다 싶어서 정리한다!
- 포인터/ 포인터를 가리키는 포인터
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main(void) {
double num = 3.14;
double* ptr = #
double** dptr = &ptr;
printf("%p %p %p\n", ptr, *dptr, dptr); //ptr ptr &ptr (ptr=&num)
printf("%f %f %f %f\n", num, *ptr, **dptr, *(*dptr)); //3.14 3.14 3.14 3.14
return 0;
}
double* ptr = &num | double 형의 포인터형 변수 ptr을 정의. ptr은 num의 주솟값을 가리킨다. |
&ptr | ptr 포인터변수의 주솟값. num의 주솟값을 가리키는 ptr의 주소를 가리킴. |
*ptr | ptr이라는 포인터변수의 값은 무엇인지 알려줌. |
- ptr : a pointer to an integer(num)
- dptr : a pointer to a pointer(ptr) to an integer(num)
- 포인터와 배열
#include <stdio.h>
#include <stdlib.h>
void main() {
int i;
int list[5]; //5개의 메모리를 저장할 수 있는 배열 생성
for (i = 0; i < 5; i++) list[i] = i + 101;
printf("%d\n", list[0]); //list의 첫번째 값을 찍어라 101
printf("%d\n", *list); //list가 가리키는 주소값 value를 찍어라 101
printf("%d\n", list[1]); //102
printf("%d\n", *(list+1));//102 //1byte뒤의 값이 아닌, 4byte 뒤의 값을 가리킴
printf("%p: %d\n", &list[1], list[1]);
printf("%p: %d\n", (list + 1), *(list + 1)); //두 식의 주소와 value는 같다. 0004 102
//각각 adress와 value를 출력하라.
//이때 4byte씩 차이가 남. //한 byte의 차이가 아니라 한 칸의 차이!
printf("%p: %d\n", (list), *(list)); //0000 101
printf("%p: %d\n", (list + 1), *(list + 1)); //0004 102
printf("%p: %d\n", (list + 2), *(list + 2)); //0008 103
}
-> &list[1] 과 list + 1은 같고, list[1] 과 *(list + 1)은 같다!
list | a pointer to list[0] ; 배열 첫번째 값의 주소 |
list + i | a pointer to list[i] ; 배열 i번째 값의 주소 |
(list + i) | &list[i] ; 배열 i번째 값 주소 |
*(list + i) | list[i] ; 배열 i번째 내용물(값)에 접근 |
- 간단한 포인터 배열 예시코드 #1 (배열 값 합하는 함수)
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
float sum(float[], int);
float input[MAX_SIZE], answer;
int i;
void main() {
for (i = 0; i < MAX_SIZE; i++) //0~99까지의 합
input[i] = i;
answer = sum(input, MAX_SIZE); //->4950.000000
printf("The sum is: %f\n", answer);
}
float sum(float list[], int n) {
int i;
float tempsum = 0;
for (i = 0; i < n; i++)
tempsum += list[i];
return tempsum;
}
출력은 4950.000000으로 나온다.
이때 sum()함수에서 list의 포인터로의 역참조가 일어난다.
또한 list[i], 즉 *(list+i) 값을 꺼내어 합한다.
- 간단한 포인터 배열 예시코드 #2 (포인터 주소/값 출력하는 함수)
#include <stdio.h>
#include <stdlib.h>
void print1(int*, int);
void main() {
int one[] = { 0,1,2,3,4 }; //배열 초기화
print1(one, 5);
}
void print1(int* ptr, int rows) { //void print1(int ptr[], int rows) { 와 같음
/*print out a one-dimensional array using a pointer*/
int i;
printf("address contents\n");
for (i = 0; i < rows; i++)
printf("%8p%5d\n", ptr + i, *(ptr + i)); //각각의 주소와 각각의 값 반환
}
- 동적할당을 하는 이유?
: 위 예시까지는 모두 배열의 크기가 정해져있다. 하지만 만약, 사용자가 입력하는 값에 따라 배열을 다르게 만들고 싶다면 어떻게 해야할까?
해결법 후보1. 배열을 무작정 크게 만든다.
-> 배열 지정한 것보다 실제값이 사이즈가 작으면 메모리를 낭비하게 된다.
-> 만약, 배열 지정한 것보다 실제값이 사이즈가 크면 프로그램이 멈추거나 다른 프로그램의 variable의 memory를 쓰게 되는 대참사가 일어난다.
해결법 후보2. 실행할 때마다 메모리를 할당해주어 배열크기만큼의 사이즈로 정한다.
-> 동적할당!
- 동적할당해서 1차원 배열
* void* malloc(size_t size)는 int data[4]와 같은 효과로서,
size의 메모리 블록만큼 값을 할당하고 블록의 시작지점에 있는 포인터를 반환한다.
** 메모리 해제 free()는 필수!
- 아래는 사용자가 입력한 수만큼에 따라 랜덤한 값의 배열을 만드는 예제이다.
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
void main() {
int i, n, m, * data;
printf("How many integers do you want to generate?");
scanf("%d", &n);
data = (int*)malloc(n * sizeof(int)); //사용자 입력만큼 동적할당해서 포인터 반환
printf("memory allocated at %p\n", data);
for (i = 0; i < n; i++)
data[i] = rand() % 100; //배열 안에 랜덤 값 지정
printf("How many integers do you want to generate additionally?");
scanf("%d", &m);
data = (int*)realloc(data, (n + m) * sizeof(int)); //추가로 받은 값만큼 더 해서 재할당
if (data == NULL) exit(1);
printf("memory reallocated at %p\n", data);
for (i; i < n + m; i++)
data[i] = rand() % 100;
for (i = 0; i < n + m; i++)
printf("%3d: %8d\n", i + 1, data[i]);
free(data); //메모리를 반납!
}
-> realloc할 때엔 그 adress를 유지하며 뒤에 추가하는 걸 우선으로 하지만,
뒤 메모리 공간이 부족하다면 기존의 공간으로부터 새로운 메모리 공간으로 데이터를 복사해서 다른공간에서 할당되어 사용된다.
- 동적할당해서 2차원 배열
#include <stdio.h>
#include <stdlib.h>
#define _CRT_SECURE_NO_WARNINGS
int** make2dArray(int, int);
void main() {
int i, j;
int** matrix;
matrix = make2dArray(5, 5);
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
matrix[i][j] = i * 5 + j + 1;
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
/*free memory*/
for (i = 0; i < 5; i++)
free(matrix[i]);
free(matrix);
}
int** make2dArray(int rows, int cols) {
int** x, i;
/*allocate memory for row pointers*/
x = (int**)malloc(rows * sizeof(*x));
/*allocate memory for each row*/
for (i = 0; i < rows; i++)
x[i] = (int*)malloc(cols * sizeof(**x));
return x;
}
- make2dArray() 함수
: 2차원 배열의 x를 반환,
1) x (int**형 변수)에 대한 row(int *)만큼의 메모리를 할당하고,
2) x* (int*형 변수)에 대한 col(int **)만큼의 메모리를 할당한다.
-> malloc대신 calloc도 사용가능.
void* calloc(size_t num, size_t size)
하지만 malloc과 다르게 처음에 0으로 초기화를 한다는 점이 있다!
- 2차원 배열 생성과 해체 (free) 코드 참고!
int i, j;
int** matrix;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
matrix[i][j] = i * 5 + j + 1;
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
/*free memory*/
for (i = 0; i < 5; i++)
free(matrix[i]);
free(matrix);
'algorithm' 카테고리의 다른 글
[ 프로그래머스 | 2022 kako tech internship ] 코딩 테스트 공부 문제 풀이 c++ (0) | 2023.11.20 |
---|---|
[ 프로그래머스 | 2022 kako tech internship ] 두 큐 합 같게 만들기 시간초과 해결 (0) | 2023.11.10 |
합병 정렬 (Merge Sort) (0) | 2020.07.25 |
정렬 알고리즘 종류 (0) | 2020.07.24 |
멱집합(Powerset) (0) | 2020.07.23 |