C Programming Language/C

Cμ–Έμ–΄ 포인터(pointer)의 κ°œλ… ν•™μŠ΅ν•˜κΈ°

567Rabbit 2024. 7. 2. 22:47

 

λ³€μˆ˜μ™€ λ©”λͺ¨λ¦¬

- λ³€μˆ˜λŠ” λ©”λͺ¨λ¦¬μ— μ €μž₯λœλ‹€

- λ©”λͺ¨λ¦¬λŠ” λ°”μ΄νŠΈ λ‹¨μœ„λ‘œ μ•‘μ„ΈμŠ€ λœλ‹€

- λ³€μˆ˜μ˜ 크기에 λ”°λΌμ„œ μ°¨μ§€ν•˜λŠ” λ©”λͺ¨λ¦¬ 곡간이 달라진닀 ex) int 4λ°”μ΄νŠΈ, char 1λ°”μ΄νŠΈ ,,,

 

 

 

 

λ³€μˆ˜μ˜ μ£Όμ†Œ

- λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό κ³„μ‚°ν•˜λŠ” μ—°μ‚°μž : &

- λ³€μˆ˜ i의 μ£Όμ†Œ : &i

 

 

 

 


ν¬μΈν„°λž€?

μ£Όμ†Œλ₯Ό κ°–κ³ μžˆλŠ” λ³€μˆ˜   ( = λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό κ°€μ§€κ³  μžˆλŠ” λ³€μˆ˜)

μ£Όμ†Œκ°’μ„ κ°€μ§„ λ³€μˆ˜

 

<ν¬μΈν„°μ˜ μ„ μ–Έ>

int * p ; 

 

- μ •μˆ˜λ₯Ό κ°€λ¦¬ν‚€λŠ” 포인터 p

 

 

 

 

 

 

포인터와 λ³€μˆ˜μ˜ μ—°κ²°

c, h
λ‹«κΈ°
int i = 10; // μ •μˆ˜ν˜• λ³€μˆ˜ i μ„ μ–Έ int *p; // 포인터 λ³€μˆ˜ p μ„ μ–Έ p = &i; // λ³€μˆ˜ i의 μ£Όμ†Œκ°€ 포인터 p둜 λŒ€μž…

 

 

 

 

 

 

&μ—°μ‚°μžμ™€ *μ—°μ‚°μž

 

&μ—°μ‚°μž : λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ°˜ν™˜ν•œλ‹€

*μ—°μ‚°μž : 포인터가 κ°€λ¦¬ν‚€λŠ” 곳의 λ‚΄μš©μ„ λ°˜ν™˜ν•œλ‹€

 

 

 

 

 

 

 

κ°„μ ‘ μ°Έμ‘° μ—°μ‚°μž *

 

: 포인터가 κ°€λ¦¬ν‚€λŠ” 값을 κ°€μ Έμ˜€λŠ” μ—°μ‚°μž

: μ§€μ •λœ μœ„μΉ˜μ—μ„œ ν¬μΈν„°μ˜ νƒ€μž…μ— 따라 값을 읽어듀인닀.

c, h
λ‹«κΈ°
int i = 10; int *p; p = &i; printf("%d", *p); // 10이 좜λ ₯λœλ‹€.

 

c, h
λ‹«κΈ°
#include <stdio.h> int main(void) { ​​​​int i = 10; ​​​​int *p; ​​​​ ​​​​p = &i; ​​​​printf("i = %d\n", i); // 10 좜λ ₯ ​​​​ ​​​​*p = 20; // 포인터λ₯Ό ν†΅ν•˜μ—¬ λ³€μˆ˜μ˜ 값을 변경함 ​​​​printf("i = %d\n", i); // 20 좜λ ₯ ​​​​return 0; ]

 

 

 

 

 

 

포인터 μ‚¬μš©μ‹œ 주의점 (1) μ“°λ ˆκΈ°κ°’(data)

 

- μ΄ˆκΈ°ν™”κ°€ μ•ˆλœ 포인터λ₯Ό μ‚¬μš©ν•˜λ©΄ μ•ˆλœλ‹€.

- 포인터가 ν•˜λ“œμ›¨μ–΄λ‘œ 감지될 경우, 해킹될 μœ„ν—˜μ„±μ΄ μžˆλ‹€. 

c, h
λ‹«κΈ°
int main(void) { ​​​​int *p; // 포인터 pλŠ” μ΄ˆκΈ°ν™”κ°€ μ•ˆλ˜μ–΄μžˆμŒ ​​​​*p = 100; // μœ„ν—˜ν•œ μ½”λ“œ ​​​​return 0; } // 포인터가 아무것도 가리킀고 μžˆμ§€ μ•ŠλŠ” κ²½μš°μ—λŠ” null둜 μ΄ˆκΈ°ν™” ν•΄μ•Ό 함 // null 포인터λ₯Ό κ°€μ§€κ³  κ°„μ ‘ μ°Έμ‘°ν•˜λ©΄ ν•˜λ“œμ›¨μ–΄λ‘œ 감지할 수 μžˆλ‹€ int *p = NULL;

 

 

 

 

 

포인터 μ‚¬μš©μ‹œ 주의점 (2) ν¬μΈν„°μ˜ νƒ€μž…κ³Ό λ³€μˆ˜μ˜ νƒ€μž…μ€ μΌμΉ˜ν•˜μ—¬μ•Ό ν•œλ‹€

c, h
λ‹«κΈ°
#include <stdio.h> int main(void) { ​​​​int i; ​​​​double *pd; ​​​​ ​​​​pd = &i; // 였λ₯˜! doubleν˜• 포인터에 intν˜• λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λŒ€μž…ν–ˆλ‹€ ​​​​*pd = 36.5; ​​​​ ​​​​return 0; }

 

- λ³€μˆ˜μ˜ 크기에 λ”°λΌμ„œ μ°¨μ§€ν•˜λŠ” λ©”λͺ¨λ¦¬ 곡간이 달라진닀 ex) int 4λ°”μ΄νŠΈ, char 1λ°”μ΄νŠΈ ,,,

- κ·ΈλŸ¬λ―€λ‘œ ν• λ‹Ήλœ μ£Όμ†Œμ— λ³€μˆ˜μ˜ νƒ€μž…μ΄ μΌμΉ˜ν•˜μ§€ μ•ŠμœΌλ©΄ 데이터가 λ§κ°€μ§€λŠ” λ“±μ˜ 문제(였λ₯˜)κ°€ 생긴닀.

 

 

 

 

 

 

포인터 μ—°μ‚°

 

- κ°€λŠ₯ν•œ μ—°μ‚° : 증가, κ°μ†Œ, λ§μ…ˆ, λΊ„μ…ˆ μ—°μ‚°

 

- 증가 μ—°μ‚°μ˜ 경우 μ¦κ°€λ˜λŠ” 값은 (포인터가 κ°€λ¦¬ν‚€λŠ” 객체의 크기)μ—μ„œ μ¦κ°€λœλ‹€. 

- λ°”μ΄νŠΈλ‘œ μ¦κ°€λœλ‹€.

 

포인터λ₯Ό λ§μ…ˆν•œλ‹€μ˜ 의미 μ•Œμ•„λ³΄κΈ°

ex) *(p + 1)

μ£Όμ†Œλ₯Ό ν•œμΉΈμ„ 더 κ°”λ‹€(1만큼 λ”ν•œλ‹€μ˜ 의미) -> ν•œμΉΈμ— β˜…λ°”μ΄νŠΈ -> β˜…λ°”μ΄νŠΈλ₯Ό 더해쀀닀

ex)  *(p + 2)

μ£Όμ†Œλ₯Ό 두칸을 더 κ°”λ‹€(2만큼 λ”ν•œλ‹€μ˜ 의미) -> ν•œμΉΈμ— 2xβ˜…λ°”μ΄νŠΈ -> 2xβ˜…λ°”μ΄νŠΈλ₯Ό 더해쀀닀

ex)  *(p + 3) 

μ£Όμ†Œλ₯Ό 세칸을 더 κ°”λ‹€(3만큼 λ”ν•œλ‹€μ˜ 의미) -> ν•œμΉΈμ— 3xβ˜…λ°”μ΄νŠΈ -> 3xβ˜…λ°”μ΄νŠΈλ₯Ό 더해쀀닀

 

 

 

 

 

κ°„μ ‘ μ°Έμ‘° μ—°μ‚°μžμ™€ 증감 μ—°μ‚°μž

 

*p++;

: pκ°€ κ°€λ¦¬ν‚€λŠ” μœ„μΉ˜μ—μ„œ 값을 κ°€μ Έμ˜¨ ν›„ pλ₯Ό μ¦κ°€ν•œλ‹€.

: 원본값은 κ·ΈλŒ€λ‘œ 있고, 포인터가 κ°€μ Έμ˜¨ κ°’λ§Œ μ¦κ°€ν•œλ‹€.

 

(*p)++;

: pκ°€ κ°€λ¦¬ν‚€λŠ” μœ„μΉ˜μ˜ 값을 μ¦κ°€ν•œλ‹€.

: 원본값이 달라진닀.

 

 

 

 

 

ν¬μΈν„°μ˜ ν˜•λ³€ν™˜

 

- cμ–Έμ–΄μ—μ„œλŠ” κΌ­ ν•„μš”ν•œ κ²½μš°μ—, λͺ…μ‹œμ μœΌλ‘œ ν¬μΈν„°μ˜ νƒ€μž…μ„ λ³€κ²½ν•  수 μžˆλ‹€.

c, h
λ‹«κΈ°
double *pd = &f; int *pi; pi = (int *)pd; //pdλ₯Ό intν˜•μœΌλ‘œ λ³€ν™˜ν•˜μ—¬μ„œ μ €μž₯ν•˜κ² λ‹€

 

 

 

 

 

 

 

인수 전달 방법

 

- ν•¨μˆ˜ 호좜 μ‹œμ— 인수 전달 방법

 

 

(1) 값에 μ˜ν•œ 호좜 (call by value)

- ν•¨μˆ˜λ‘œ 볡사본이 μ „λ‹¬λœλ‹€

- 기본적인 방법

- 데이터가 크면 잘 μ•ˆμ“΄λ‹€. 볡사가 되면 μš©λŸ‰μ„ 많이 μ°¨μ§€ν•˜λ―€λ‘œ.

 

 

 

(2) 참쑰에 μ˜ν•œ 호좜 (call by reference)

- ν•¨μˆ˜λ‘œ 원본이 μ „λ‹¬λœλ‹€

- Cμ—μ„œλŠ” 포인터λ₯Ό μ΄μš©ν•˜μ—¬ 흉내낼 수 μžˆλ‹€

 

 

*px, *pyλ₯Ό 

(μ£Όμ†Œλ‘œ κ°€μ„œ)

&a, &b

swap (λ°”λ€Œλ―€λ‘œ) λ˜λ―€λ‘œ,

원본이 λ°”λ€ŒλŠ” 것이닀.

 

 

 

 

 

 

 

scanf() ν•¨μˆ˜ λ‹€μ‹œ 이해해보기 : ν¬μΈν„°μ˜ κ°œλ…

 

scanf("%d", &x

 

: λ³€μˆ˜μ— 값을 μ €μž₯ν•˜κΈ° μœ„ν•˜μ—¬ λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ°›λŠ”λ‹€

: μ „λ‹¬λœ μ£Όμ†Œλ₯Ό μ΄μš©ν•΄ λ³€μˆ˜μ— μ‚¬μš©μžλ‘œλΆ€ν„° 받은 값을 μ €μž₯ν•œλ‹€.

 

 

 

 

 

 

 

 

 

포인터와 λ°°μ—΄

 

- λ°°μ—΄κ³Ό ν¬μΈν„°λŠ” μ•„μ£Ό λ°€μ ‘ν•œ 관계λ₯Ό κ°€μ§€κ³  μžˆλ‹€.

- λ°°μ—΄ 이름이 λ°”λ‘œ 포인터이닀.

- ν¬μΈν„°λŠ” λ°°μ—΄μ²˜λŸΌ μ‚¬μš©μ΄ κ°€λŠ₯ν•˜λ‹€.

- 인덱슀 ν‘œκΈ°λ²•μ„ 포인터에 μ‚¬μš©ν•  수 μžˆλ‹€.

 

 

 

 

%uλŠ” μ£Όμ†Œλ₯Ό μ˜λ―Έν•œλ‹€.

 

 

 

 

 

 

int b[]

int *b

- κ°™μ€ν‘œν˜„μ΄λ‹€.

 

c, h
λ‹«κΈ°
void sub(int b[], int size) { ​​​​*b = 4; ​​​​*(b+1) = 5; ​​​​*(b+2) = 6; ​​​​ ​​​​// 포인터 bλ₯Ό ν†΅ν•˜μ—¬ 원본 배열을 λ³€κ²½ν•  수 μžˆλ‹€. }

 

포인터λ₯Ό ν†΅ν•œ λ°°μ—΄μ˜ 변경은 참쑰에 μ˜ν•œ 호좜 (call by reference)둜 원본이 λ°”λ€Œκ²Œ λœλ‹€.

 

 

 

 

 

 

 

포인터λ₯Ό μ‚¬μš©ν•œ λ°©λ²•μ˜ μž₯점

 

- 포인터가 인덱슀 ν‘œκΈ°λ²•λ³΄λ‹€ λΉ λ₯΄λ‹€.

- 인덱슀λ₯Ό μ£Όμ†Œλ‘œ λ³€ν™˜ν•  ν•„μš”κ°€ μ—†λ‹€.

=> 속도가 μ—„μ²­ λΉ λ₯Έκ²ƒμ€ μ•„λ‹ˆλ‹ˆ, ν•„μš”μ— 따라 μ‚¬μš©ν•˜λ©΄ λœλ‹€.

 

 

 

 

 

 

 

포인터λ₯Ό λ°˜ν™˜ν•  λ•Œ 주의점

 

- ν•¨μˆ˜κ°€ μ’…λ£Œλ˜λ”λΌλ„ 남아 μžˆλŠ” λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ°˜ν™˜ν•˜μ—¬μ•Ό ν•œλ‹€.

- μ“°λ ˆκΈ°κ°’μ΄ λ‚¨μ•„μžˆλŠ” 것을 λ°©μ§€ν•˜κΈ° μœ„ν•¨μ΄λ‹€.

- μ§€μ—­ λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ°˜ν™˜ν•˜λ©΄ ν•¨μˆ˜κ°€ μ’…λ£Œλ˜λ©΄ 사라지기 λ•Œλ¬Έμ— 였λ₯˜κ°€ λ°œμƒν•œλ‹€.

 

 

> 잘λͺ»λœ μ˜ˆμ œμ΄λ‹€.

c, h
λ‹«κΈ°
#include <stdio.h> int* getLocalVariableAddress() { ​​​​int localVar = 10; // μ§€μ—­ λ³€μˆ˜ ​​​​return &localVar; // μ§€μ—­ λ³€μˆ˜μ˜ μ£Όμ†Œλ₯Ό λ°˜ν™˜ (문제 λ°œμƒ) } int main() { ​​​​int* p = getLocalVariableAddress(); ​​​​// ν•¨μˆ˜ μ’…λ£Œ ν›„ μ§€μ—­ λ³€μˆ˜λŠ” μ‚¬λΌμ§€λ―€λ‘œ pλŠ” μœ νš¨ν•˜μ§€ μ•Šμ€ μ£Όμ†Œλ₯Ό 가리킴 ​​​​printf("Value at p: %d\n", *p); // 잘λͺ»λœ μ ‘κ·Ό (μ˜ˆμƒμΉ˜ λͺ»ν•œ κ²°κ³Ό λ°œμƒ) ​​​​return 0; }

 

 

> μ˜¬λ°”λ₯Έ μ˜ˆμ œμ΄λ‹€.

c, h
λ‹«κΈ°
#include <stdio.h> #include <stdlib.h> int* getDynamicMemoryAddress() { ​​​​int* ptr = (int*)malloc(sizeof(int)); // 동적 λ©”λͺ¨λ¦¬ ν• λ‹Ή ​​​​if (ptr == NULL) { ​​​​​​​​printf("Memory allocation failed\n"); ​​​​​​​​exit(1); ​​​​} ​​​​*ptr = 10; // 동적 λ©”λͺ¨λ¦¬μ— κ°’ ν• λ‹Ή ​​​​return ptr; // 동적 λ©”λͺ¨λ¦¬μ˜ μ£Όμ†Œλ₯Ό λ°˜ν™˜ (문제 μ—†μŒ) } int main() { ​​​​int* p = getDynamicMemoryAddress(); ​​​​printf("Value at p: %d\n", *p); // μ˜¬λ°”λ₯Έ μ ‘κ·Ό ​​​​free(p); // 동적 λ©”λͺ¨λ¦¬ ν•΄μ œ ​​​​return 0; }

 

 

 

 

 

 

예제) 5x5 이미지 λ˜λŠ” μ˜μƒμ˜ ν–‰λ ¬μ˜ 밝기λ₯Ό 10만큼 μ¦κ°€μ‹œν‚€λŠ” 예제

 

c, h
λ‹«κΈ°
#include <stdio.h> #define SIZE 5 void print_image(int image[][SIZE]) { ​​​​int r, c; ​​​​for (r = 0; r < size; r++){ ​​​​​​​​for (c = 0; c < size; c++){ ​​​​​​​​​​​​printf("%03d", image[r][c]); ​​​​​​​​} ​​​​​​​​printf("\n"); ​​​​} ​​​​printf("\n"); } void Brightn_image(int image[][SIZE]) { ​​​​int r, c; ​​​​int *p; ​​​​p = &image[0][0]; ​​​​for (r = 0; r < size; r++){ ​​​​​​​​for (c = 0; c < size; c++){ ​​​​​​​​​​​​*p += 10; ​​​​​​​​​​​​p++; ​​​​​​​​} ​​​​} } int main(void) { ​​​​int image[5][5] = { ​​​​​​​​{10, 20, 30, 40, 50}, ​​​​​​​​{10, 20, 30, 40, 50}, ​​​​​​​​{10, 20, 30, 40, 50}, ​​​​​​​​{10, 20, 30, 40, 50}, ​​​​​​​​{10, 20, 30, 40, 50}}; ​​​​print_image(image); ​​​​brighten_image(image); ​​​​print_image(image); ​​​​return 0; }