24강. 포인터
포인터 (pointer) = 변수의 주소를 저장하는 변수이다.
포인터를 선언할 때는
int *ptr_a; 처럼 앞에 *별을 붙인다.
int main() {
int a = 20;
int* ptr_a;
ptr_a = &a;
//&a 는 a 의 주소값
printf("%d\n", ptr_a);
}
int main() {
int a = 20;
int* ptr_a;
ptr_a = &a;
printf("a의 값: %d\n", a);
printf("a의 주소값: %d\n", &a);
printf("ptr_a에 저장된 값 : %d\n",ptr_a);
printf("ptr_a가 가리키는 변수의 값: %d\n", *ptr_a);
}
int main() {
int a = 10;
int b = 20;
int* ptr;
ptr = &a;
printf("ptr이 가리키는 변수에 저장된 값 : %d\n", *ptr);
ptr = &b;
printf("ptr이 가리키는 변수에 저장된 값 : %d\n", *ptr);
}
int main() {
int a = 10;
int* ptr;
ptr = &a;
printf("a의 값: %d\n", a);
*ptr = 20;
printf("a의 값: %d\n", a);
}
int main() {
int a = 10;
int* ptr;
ptr = &a;
int** ptr_ptr;
ptr_ptr = &ptr;
printf("a= %d\n", a);
printf("&a = %d\n", &a);
printf("ptr = %d\n", ptr);
printf("&ptr = %d\n", &ptr);
printf("ptr_ptr = %d\n", ptr_ptr);
printf("*ptr_ptr = %d\n", *ptr_ptr);
printf("**ptr_ptr = %d\n", **ptr_ptr);
}
**ptr_ptr은 *(*ptr_ptr)이랑 똑같은거니까 *ptr_ptr은 결국 ptr이니까
*ptr은 ptr이 가리키는 놈 a 가 된다.
25강. 배열, 포인터
int* ptr_a;
ptr_a = &a;
는 합쳐서
int *ptr_a = &a; 라고 써도 된다.
int main() {
int a = 10;
int* ptr_a = &a;
printf("ptr_a의 값 :%d\n", ptr_a);
printf("ptr_a +1의 값 : %d\n", ptr_a + 1);
}
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n",i, &arr[i]);
}
}
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
printf("arr의 값:%d\n", arr);
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n",i, &arr[i]);
}
}
arr 의 값 = &arr[0] 이랑 똑같다.
첫번째 원소가 들어있는 곳의 주소
arr = &arr[0]
100 100
arr+1 = &arr[0] + 1 =&arr[1]
104 104
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++) {
printf("&arr[%d] = %d\n", i, &arr[i]);
printf("arr+%d = %d\n", i, arr + i);
}
}
결국 arr + i 이거랑 &arr[i] 랑 같은말
왜 4가 더해지는가? - sizeof (int)가 4이기 때문에.
int main() {
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("\n");
for (int i = 0; i < 10; i++) {
printf("%d ", *(arr + i)); //arr+i =&arr[i]니까 *(arr + i) = *(&arr[i])
}
printf("\n");
for (int* ptr = arr; ptr < arr + 10; ptr++) {
printf("%d ", *ptr); //arr= &arr[0]
}
}
결과 : 세개의 for문이 가리키는 값이 같다.
int main() {
int arr[3] = { 1,2,3};
int* ptr = arr;
for (int i = 0; i < 3; i++) {
printf("%d ", *(ptr + i));
}
printf("\n");
for (int i = 0; i < 3; i++) {
printf("%d ", *(arr + i));
}
printf("\n");
for (int i = 0; i < 3; i++) {
printf("%d ", ptr[i]);
}
printf("\n");
for (int i = 0; i < 3; i++) {
printf("%d ", arr[i]);
}
printf("\n");
for (int i = 0; i < 3; i++) {
printf("%d ", i[arr]);
}
printf("\n");
for (int i = 0; i < 3; i++) {
printf("%d ", i[ptr]);
}
}
i[ptr]
arr[i] == *(&arr+i) == *(ptr +i) == ptr[i]
*(ptr +i) == *(i + ptr) == i[ptr]
실무에서는 i[ptr] 안쓰는게 좋다
int main() {
int arr[3] = { 1,2,3 };
int* ptr = arr;
printf(" *ptr = %d \n", *ptr);
printf(" &arr = %d \n", &arr);
printf(" ptr = %d \n", ptr);
printf(" arr = %d \n", arr);
printf(" *(&arr) = %d \n", *(&arr));
printf(" *(&ptr) = %d \n", *(&ptr));
}
*(&arr) 은 arr 이랑 똑같다.
정리
1. ptr == &ptr[0]
2. *ptr == ptr[0]
3. ptr +1 == ptr에 sizeof(*ptr)을 더한 값. (int 면 4)
int main() {
int arr[3] = { 1,2,3 };
printf("arr = %d\n", arr);
printf("arr + 1=%d\n", arr + 1);
printf("&arr = %d\n", &arr);
printf("&arr+1 = %d\n", &arr + 1);
}
왜 &arr + 1 은 4가 아니고 12가 더해졌을까?
(힌트 : arr 크기가 총 12바이트)
ptr +1 == ptr에 sizeof(*ptr)을 더한 값.
&arr +1 == arr에 sizeof(*(&arr))를 더한 값.
*(&arr)은 arr 이랑 똑같으니까
&arr + 1 == arr 에 sizeof(arr) 을 더한 값이 되므로 12가 더해져야 한다.
100 104 108 112
arr| 1 | 2 | 3 |
&arr (arr 배열 전체의 주소)= 100
&arr + 1 은 1,2,3의 다음 배열로 가야되니까 112 가 되어야 됨.
배열 포인터
1) 배열 포인터를 선언하는 방법
int main() {
int arr[3] = { 1,2,3 };
int(*ptr)[3];
ptr = &arr;
for (int i = 0; i < 3; i++) {
printf("%d ", (*ptr)[i]);
}
printf("\n");
printf("%d ", ptr);
}
길이 3인 int 형 배열을 가리키는 포인터를 선언한 것
int(*ptr)[3] = &arr; 이렇게 합쳐서 적어도 됨
int main() {
int arr[3] = { 1,2,3 };
int(*ptr)[3] = &arr;
for (int i = 0; i < 3; i++) {
printf("%d ", (*ptr)[i]);
}
printf("\n");
printf("%d ", ptr);
}
27강. 2차원 배열과 배열 포인터
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
printf("%d\n", sizeof(arr)); // 24
printf("%d\n", sizeof(arr[0])); //12
printf("%d\n", sizeof(arr[0][0]));//4
}
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
printf("%d\n", &arr);
printf("%d\n", &arr[0]);
printf("%d\n", &arr[0][0]);
}
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
int(*ptr)[3] = arr; // &arr[0]
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", ptr[i][j]);
}
printf("\n");
}
}
int(*ptr)[3] = arr; // &arr[0]
arr == &arr[0] 이 핵심!
의문점
1) ptr[i] == arr[i]
2) ptr[i][j] == arr[i][j]
3) ptr == arr
ptr 은 arr [0] (arr 배열의 첫번째 행) 을 가리키고 있다.
*(ptr+i) = 12i
ptr +1 은 그 다음행을 가리킨다.
예제)
int main() {
int arr[2][3] = { {1,2,3},{4,5,6} };
for (int(*row)[3] = arr; row < arr + 2; row++) {
for (int* col = *row; col < *row + 3; col++) {
printf("%d ", *col);
}
printf("\n");
}
}
row 는 첫번째 3칸 배열을 가리키고 있으므로 *row 자체가 하나의 배열을 의미한다.
따라서 int *col = *row 를 하면 col 에는 &(*row)[0] 이 들어가게 된다.
28강. 포인터 배열
1) 배열 포인터 : 배열을 가리키는 포인터 int(*ptr)[4]
2) 포인터 배열 : 포인터들이 배열 int *ptr[4]
int main() {
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* ptr[4]; //4칸짜리 포인터로 이루어진 배열
ptr[0] = &a;
ptr[1] = &c;
ptr[2] = &d;
ptr[3] = &b;
printf("%d %d %d %d\n", *ptr[0], *ptr[1], *ptr[2], *ptr[3]);
}
int main() {
int arr[4] = { 1,2,3,4 };
int* ptr[4];
for (int i = 0; i < 4; i++) {
ptr[i] = &arr[i];
}
for (int i = 0; i < 4; i++) {
printf("%d ", *ptr[i]);
}
printf("\n");
}
int main() {
char str[] = "Hello";
printf("%s", &str[0]);
}
%s 는 배열의 0번째 칸의 주소를 알려주면 전체 문자열을 출력
&str[0] 은 str 이랑 같으니까
prinf("%s", str); 이렇게 써도 똑같다.
int main() {
char str[3][10] = { "Hello", "World", "Doodle" };
for (int i = 0; i < 3; i++) {
printf("%s\n", str[i]);
}
}
int main() {
char str[3][10] = { "Hello", "World", "Doodle" };
for (int i = 0; i < 3; i++) {
printf("%s\n", &str[i][0]);
}
}
str[i] 는 &str[i][0] 이랑 똑같은 것
int main() {
char str[3][10] = { "Hello", "World", "Doodle" };
char* p_str[3]; //3칸짜리 캐릭터형 포인터
for (int i = 0; i < 3; i++) {
p_str[i] = str[i]; // &str[i][0] 이거랑 똑같은거
}
for (int i = 0; i < 3; i++) {
printf("%s\n", p_str[i]);
}
}
29강. 종합문제
1) 100개 이하의 정수를 입력받고 첫줄에 짝수번째 숫자들을 순서대로 출력하고 다음줄에 홀수번째 숫자들을 순서대로 출력
예를 들어 7 입력
1 2 3 4 5 6 7
출력
2 4 6
1 3 5 7
int main() {
int n;
int arr[105];
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
for (int i = 1; i < n; i += 2) {
printf("%d ", arr[i]);
}
printf("\n");
for (int i = 0; i < n; i += 2) {
printf("%d ", arr[i]);
}
printf("\n");
}
2) 다음 코드의 결과를 예측하시오.
int main() {
int a = 10;
int b = 20;
int* ptr;
ptr = &a;
*ptr = 30;
ptr = &b;
*ptr = 10;
printf("%d\n", a);
printf("%d\n", b);
printf("%d\n", *ptr);
}
결과 : 30, 10, 10
3) 다음 코드의 결과를 예측하시오.
int main() {
int arr[10] = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3 };
printf("%d\n", arr);
for (int i = 3; i < 7; i++){
printf("%d %d\n", arr + i, *(arr + i));
}
}
arr 은 arr 첫번째 원소의 주소값. 예를들어 100이라고 가정
i = 3일 때, arr + 3 은 배열 원소 자료형이 int 형이므로 4를 곱해서 12 를 더한다.
112 , *(arr +3) 은 0,1,2,3 해서 4번째 수 1
i = 4일 때, arr +4는 112 + 4 = 116, *(arr + 4)는 5번째 수 5
i= 5 120, *(arr+5) = 9
i = 6 124, *(arr+6) = 2
4) 10*10 이하의 정수형 이차원 배열을 입력 받고 그 배열의 각 행의 요소의 합을 출력하는 프로그램 만들기
입력 예
3 4
4 2 6 3
7 9 3 4
5 1 2 1
출력 예
15
23
9
int main() {
int n, m;
int arr[12][12];
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
scanf("%d", &arr[i][j]);
}
}
int sum = 0;
for (int i = 0; i < n; i++) {
int sum = 0;
for (int j = 0; j < m; j++) {
sum += arr[i][j];
}
printf("%d\n", sum);
}
}
심화문제
1) 다음 코드의 결과를 예측하시오.
int main() {
int arr[3][3] = { 0 };
printf("%d\n", &arr); //100
printf("%d\n", arr); //100
printf("%d\n", *arr); //100
printf("%d\n", &arr[0]); //100
printf("%d\n", arr[0]); //100
printf("%d\n", *arr[0]); //0
printf("%d\n", &arr[0][0]); //100
printf("%d\n", arr[0][0]); //0
}
2) 다음 코드의 결과를 예측하시오.
int main() {
int arr[3][3] = { 0 };
printf("%d\n", &arr[0][0]); //100
printf("%d\n", arr[0]+1); // 104
printf("%d\n", &arr[0]+1); // 112
printf("%d\n", arr+1); // 112
printf("%d\n", &arr + 1); // 136
}
arr[0] 은 첫번째 행의 주소값
&arr[0][0] 이거랑 같은말
arr[0] +1 은 바로 다음칸 이니까 104
&arr[0] 은 arr 랑 똑같은것 (2차원 배열 전체) +1
3) 틀린 부분 고치기
int main() {
int arr[3][4] = {
{ 1 ,2 ,3 ,4},
{5, 6 , 7, 8},
{9, 10 , 11, 12}
};
int (* ptr)[4] = arr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", *ptr[i][j]);
}
printf("\n");
}
}
int main() {
int arr[3][4] = {
{ 1 ,2 ,3 ,4},
{5, 6 , 7, 8},
{9, 10 , 11, 12}
};
int (* ptr)[4] = arr;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%d ", ptr[i][j]);
}
printf("\n");
}
}
'개발자' 카테고리의 다른 글
두들낙서 C/C++ 36강, 37강 배열을 매개변수로 넘기기, 종합문제 (0) | 2022.08.11 |
---|---|
두들낙서 C/C++ 31강~35강 함수, 함수의 반환, call by reference, 프로토 타입, 재귀 함수 (0) | 2022.06.20 |
두들낙서 C/C ++ 22강, 23강 2차원 배열, 문자열 함수 strlen, strcpy, strcat, strcmp (0) | 2022.06.17 |
두들낙서 20강, 21강 정리 - 배열 (거꾸로 출력, 최대 최소, 짝수의 개수) (0) | 2022.06.16 |
두들낙서 17강~19강 while을 for 로 바꿔보기, 중첩 for 문 예제들 (0) | 2022.06.16 |
댓글