본문 바로가기
개발자

두들낙서 C/C++ 24강~30강 포인터, 배열 포인터 , 포인터 배열 종합문제

by ⁖⁝‥ 2022. 6. 17.

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 *ptr[4]
int *ptr[4]

 

 

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");
	}
}

 

반응형

댓글