정리는 나중에 ..^^
const int *pa = &a;
const = 절대적으로 바뀌지 않는 값을 의미함
그래서 pa가 가리키는 변수 a의 값은 절대 바뀌면 안됨
*pa = 3; // 올바르지 않은 문장
pa = &b; // 올바른 문장
int const *pa = &a;
const의 위치가 바뀌었음. 이러면 const는 pa 자체를 바뀌면 안되는 값으로 지정함. pa가 가리키는 것은 a여야만 하는것임.
고로 아까랑 상황이 달라짐
pa = 3; // 올바른 문장
pa = &b; // 올바르지 않은 문장
const int* const pa = &a;
이렇게 되면 pa가 가리키는 값, 그리고 a의 값 또한 바뀔 수 없음.
배열 / 포인터
#include <stdio.h>
int main() {
int arr[3] = {1, 2, 3};
printf("arr 의 정체 : %p \n", arr);
printf("arr[0] 의 주소값 : %p \n", &arr[0]);
return 0;
}
컴파일 시 나오는 결과 :
arr 의 정체 : 0x7fff1e868b1c
arr[0] 의 주소값 : 0x7fff1e868b1c
배열의 이름과 첫번째 원소의 주소값은 다름. 근데 결과값이 같게 나온 이유는 배열의 이름이 sizeof 연산자나 주소값 연산자 &와 사용될 때가 아니라면, 배열의 이름을 사용시 암묵적으로 첫 번째 원소를 가리키는 포인터로 타입 변환됨. 그래서 arr이라고 입력했을 때 arr[0]의 주소값이 프린트 되는 것임.
arr은 sizeof를 사용하지 않았고 &도 사용하지 않았기 떄문에 첫번째 원소를 가리키는 포인터로 타입 변환되었음.
/* 신기한 [] 사용 */
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
printf("3[arr] : %d \n", 3 [arr]);
printf("*(3+a) : %d \n", *(arr + 3));
return 0;
}
arr[3] = *(arr+3)
둘다 출력값은 4임
[]는 연산자임. []를 사용할 시 위와 같이 사용됨. 그리고 arr은 + 연산자와 사용되기 때문에 첫번째 원소를 가리키는 포인터로 변환되어서 arr+3이 포인터 덧셈을 수행하게 되는거임.
그리고 3 [arr]같은 경우는 arr[3]과 같음. 왜냐하면 *(3+arr)로 바꿔주기 떄문에 arr[3]과 같은 값으로 출력되는 거임.
그렇다면 arr[3][3]과 같은 경우에는 어떤 식으로 바꿔줘야할까?
*(*(arr + 3) + 3)
위와 같음.
arr[3][3] = {1,2,3,4,5,6,7,8,9}라고 가정하겠음.
arr[x]는 크기가 12임. arr[x][y]는 크기가 4임. arr[3][3]의 경우에는 크기가 36이고 주소값은 48이 됨. (int 기준)
arr[3] = (arr + 3) = 크기 36
arr[3][3] = (arr + 3)에 +3을 해주면 36 + 3가 아니고 36 + 4 3이 됨. 왜냐면 arr[x][y]크기가 4이므로 4만큼 3번을 더하라는 소리가 돼서 43인거임.
+1은 배열의 원소 크기(메모리적인)만큼 이동하라는 의미임.
2차원 배열을 가리키는 포인터를 통해서 원소에 접근하기 위해서는
1. 가리키는 원소의 크기
2. y의 값을 알아야함
그래서 이렇게 써줌
int arr[2][3];
int (*ptr)[3]; // << 크기가 3인 배열을 가리키는 포인터
ptr = arr;
1차원 배열에서 배열의 이름이 첫번째 원소를 가리키는 포인터로 타입 변환이 된 것처럼(e.g. arr), 2차원 배열에서 배열의 이름이 첫번째 행을 가리키는 포인터로 타입 변환이 되어야함.
int* arr[3]은 int형 포인터를 요소로 가지는 배열이기 때문에 arr안에 있는 내용은 모두 주소값임. 걍 쉽게 주소값 담을 배열이란거임 ..
malloc
arr = (int *) malloc(sizeof(int) * sizeofarray);
int로 malloc 사이즈 할당/ array 만들거기 때문에 sizeof(int) * 배열 크기만큼의 메모리를 malloc으로 할당해줄거임
즉 arr[] = arr[sizeofarray]
free(arr);를 통해 다 쓰고 난 후에 메모리 영역을 다시 리턴함.
2차원 배열 동적할당
포인터 배열을 동적으로 할당한 뒤에 다시 포인터 배열의 원소들이 가리키는 일차원 배열을 다시 동적으로 할당해줌 >> 실질적으로 따지면 2차원 배열은 아닌데 2차원 배열처럼 사용할 수 있음.
이거 정리는 나중에!
/* 2 차원 배열의 동적 할당 */
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i;
int x, y;
int **arr; // 우리는 arr[x][y] 를 만들 것이다.
printf("arr[x][y] 를 만들 것입니다.\n");
scanf("%d %d", &x, &y);
arr = (int **)malloc(sizeof(int *) * x);
// int* 형의 원소를 x 개 가지는 1 차원 배열 생성
for (i = 0; i < x; i++) {
arr[i] = (int *)malloc(sizeof(int) * y);
}
printf("생성 완료! \n");
for (i = 0; i < x; i++) {
free(arr[i]);
}
free(arr);
return 0;
}
*(newnode).data = newnode -> data
malloc / calloc / realloc
arr = (int *)malloc(sizeof(int) * 200)
arr = (int *)calloc(200, sizeof(int))
사용방법이 다름
그리고 malloc은 배열 안에 값이 쓰레기값으로 채워지는데 calloc은 값이 0으로 채워짐
realloc - 할당된 배열 크기 재조정
arr = realloc(arr, 300 * sizeof(int))