다시 오신 걸 환영해요
이번 강의에서는 참조로 넘어가기라는 개념을 다룰 거예요
처음 포인터에 관해 얘기할 때 장점 중 하나를 언급했죠 전역
변수를 많이 안 써도 된다고요
함수에 포인터를 전달하면 함수들이
매개 변수를 사용할 수 있거든요 매개 변수를 변경하면 데이터는
함수 밖에서 수정되죠
이건 아주 귀중한 개념이에요
얘기 좀 해요 이건 콘셉트예요 C는 이걸 안 써요
이게 어떻게 작동하는지 예제를
몇 개 보여드릴게요
값이 그냥 지나간다는 개념이 있어요 함수와 관련 있어요
함수에 데이터를 전달하는 것에 대해 얘기했었죠 컴파일러 내 언어의
관점에서 어떻게 전달되는지를요
지나간 값이란 개념이 있어요 우리가 지금까지
얘기했던 게 이거죠 scanf 함수 외의
함수를 호출할 때마다 다른 함수를 호출할 때마다
함수 안의 데이터를 수정하면 함수 밖에서는
수정되지 않아요
로컬 변수 얘길 했는데 좀 다른 개념이죠
데이터를 함수에 전달할 때 두 가지 방법이 있어요
값으로 넘길 수도 있고 참조로 넘길 수도 있어요
C는 값으로만 전달하고 jva도
그래요 모두 값으로
전달하죠 하지만 주소를 복사하기 때문에
참조를 거치죠
따라서 이 컨셉트 패스는
c가 특별히 사용하진 않지만 시뮬레이션을
하는 거죠 참조의 의미와 그게 왜 중요한지
이해하기 위해 얘기를 나눠보죠
하지만 넘김 값이란 함수가 인수의 실제 값을 함수의 형식적
매개 변수로 복사하는 거예요
그래서 부동 소수점 수로 정수나 더블을
가지고 함수에 대한 인수로 넘기면 실제 변수는
함수 밖에서 수정되지 않아요 복사되니까요
함수 안의 매개 변수에 수정이 이루어져도 인수에 아무 영향이 없죠
통과된 논거는 수정되지 않아요
복사본이기 때문에 로컬 변수처럼 행동하죠
보닛 밑에서 실제로 일어나는 일은 복사되어 함수에 전달되는 거죠
C 프로그램은 인수를 전달하기 위해 Call by value를 사용하죠.
모든 걸 값으로 부르고 값으로 넘겨요
이런 용어들을 교환해서 사용하죠
다시 말해 함수 내의 코드는 함수를 호출하는 데 사용된 인수를 바꿀 수 없다는 거죠
함수 안에서 바뀌긴 했지만 값에는 변화가 없어요
지역 변수인 것 같아요
그래서 지금까지 전역 데이터를 생성해야
할 때 한 함수에서 다음 함수까지 데이터를 공유하고 싶다면요
C는 이렇게 작동해요
하지만 주소 사본을 전달하면 어떻게
될까요? 참고 자료로 모방할 수 있어요
그런데 우리가 패스 바이 값을 어떻게 사용했는지 예가 여기 있어요 아주 잘 보여져 있죠
스와핑 루틴은 종종 사용 사례로 값을 통과시키는 걸
시연합니다 임시직을 생성하고 인수가 통과되는 매개 변수를
스와핑하거든요
스와프라는 함수가 있는데 두 개의 정수를 넣고 로컬
변수 temp를 만들게요
x를 temp로 매개변수에 할당하면 temp는
x가 되겠죠 x가 y와 같다고 하면 y가
x와 같아지는 거죠 y가 temp와 같다고 하면
y는 temp와 같겠죠
이 값을 전달하는 함수를 호출하면 x와
y는 이 함수에 로컬이 되죠
이 변수들은 이 함수 밖에서 수정되지 않아요
이 함수는 그걸 아주 유용하게 보여줍니다 y엔
할당하고 x엔 할당하고 있으니까요
x와 y는 이 함수에서 로컬이죠 값으로 넘기고 있으니까요
이 함수 밖에서는 수정되지 않아요 그래서 전역 변수를 써야 하죠
그냥 정수잖아요 두 개의 정수 x와 y예요 주소가 아니라 정수예요
의미 있는 거죠
swap을 눌러서
어떤 모습인지 보면 값이 바뀌지
않은 걸 알 수 있죠
100 b라는 변수를 생성하고 200과
바꾸기 전에 변수를 프린트하고 100과 200
다음에 바꾸기를 호출하면
변수는 다시 프린트한 후에
바뀌지 않아요
코드 블록에서 이걸 보죠 값으로 전달하는 게 시연될 거예요
여기 예제가 있어요 교대 시간이 있어요
x와 y를 통과한 데이터의 값을 바꾸고 있어요
100달러 200센트요
함수를 호출하기 전에 프린트할 거예요
나중에 프린트할 거예요
변수 a와 b는 절대 변하지 않아요
그 이유는 우리가 패스 바이 값이란 걸 하기 때문이죠
이 프로그램을 실행하면 a 값을 100으로
바꾸기 전에 볼 수 있습니다. a 값을 100으로 바꾸고 나서 b 200, 200도 똑같이
바꾸는 것을 볼 수 있어요.
그 이유는 값을 넘겼기 때문이죠 참조를 통과하면 호출
후에 변수 a와 b가 바뀌어요
같은 테크닉인 패스 바이 값을 이용하되 포인터를 복사하면
어떨까요? 어떤 일이 일어날까요?
포인터와 함수는 아주 잘 어울리죠
함수에 인수로 포인터를 전달할 수도
있고 함수가 결과로 포인터를 반환하게 할 수도 있어요
어떻게 하는지도 보여드릴 거예요
하지만 참조로 인수의 주소를 형식적인 매개 변수로 복사하죠
통화에 사용된 실제 인수에 접근하려면 주소가 필요해요
함수 내 매개 변수의 변화가 호출에
있는 인수에 영향을 준다는 뜻이죠
엄밀히 말하면 후드 아래에서 참조한 게 아니지만
참조한 걸 모방하거나 모방한 거죠
주소를 복사하고 있어요 주소를 복사하면 새
주소와 그 값에 대한 메모리를 갖게 되죠
하지만 해당 주소를 할당하려 하면 그 주소를 할당하죠
그래서 값으로 통과했어도 복사를 하는 거죠
정수를 복사하고 있다면 변경하지 않아요 주소를 복사하면 주소가 메모리에
있어요 그래서 수정을 하면 해당 주소를 수정하게 되죠
참조로 값을 전달하려면 인수
포인터를 함수에 전달해야 합니다 다른 값과 마찬가지로요
함수 매개 변수를 별표와 함께 포인터 유형으로 선언해야 해요
함수 안의 변화는 함수 밖에서도 반영되죠
전역 변수를 많이 사용하지 않아도 돼요
반면, 함수 밖에서 변화가 반영되지 않는 call by value는 다르죠
여전히 복사를 하고 값을 넘기고 있어요 주소의 값일 뿐이죠
이해하셔야 할 중요한 개념이에요
swap 함수를 만들 때 declaration과
함께 만들 거예요 함수 안에 asterix, star와
star로요
이 함수는 포인터를 받아요
이 함수 안에 인다이렉션 연산자를
써서 데레퍼링을 해야 합니다 값을 할당해야
하니까요 x가 점을 찍는 x 값을
임시로 할당할 거예요
x 포인트의 값을 y 포인트의 값에 할당하고
y 포인트의 값을 temp에 할당할 거예요
템프는 정수라서 체제할 필요가 없어요
A100과 b200을
A와 B로 전달하면 이 두 가지는
포인터가 아니라서 포인터를 받는 함수라서 주소를 전달해야
해요
포인터를 취하는 함수가 있을 때마다 포인터를 선언하지 않으면 연산자의
주소를 사용해야 합니다 scanf를 사용하는 것과 마찬가지죠
호출 후에 변수 a와 b를 바꾸기
위해 이것을 호출하면 바뀐 것을 볼 수 있습니다. 바뀐
것을 볼 수 있어요. A는 200 b는 100이 되죠
이제 이 예제를 보죠 스와프 메서드를 코드블록에서 포인터로 변경하면서요
코드 블록이에요 포인터를 받기 위해 스와프 기능을 수정했어요
배정할 때 규제를 풀어야 해요
이제 a와 b의 주소도 전달합니다 왜냐하면 이것들은 정수이고 스와프는
포인터를 취하기 때문이죠 이걸 실행하면 호출과 그
이후가 이제 바뀌는 걸 볼 수 있어요
바꾸기 전 A는 100이고 바꾸기 전은 200이죠
중고품으로 바꾸기 전에는 200파운드예요 그다음은 100달러예요
함수 안에서 변수의 값을 바꿀 수 있어요
주소를 복사하고 있으니까요 포인터의 가장 큰
장점 중 하나죠
구문을 요약해보죠 이미 했지만 좀 더 자세히 살펴보죠
한 변수에 대한 두 가지 정보를 함수와 통신할 수 있어요
x의 값을 전송할 수 있고 그
함수는 x와 같은 형식으로 선언되어야 하죠
우리도 알아요 함수에 데이터를 전달할
때마다 같은 형식을 호출해야 하죠
int function1을 호출할 수 있고 int num으로 정의되어 있죠
그래서 함수에서 x의 값을 전송할 때 같은 형식으로 선언되어야 하죠
그런 다음 x 주소를 실제로 호출하려면 올바른 형식에
포인터를 포함하기 위해 함수 정의를 요구하죠
포인터를 사용할 때마다 데이터를 넘겨줄 때 그 데이터가
포인터가 아니라면 그 주소를 알아야 해요
요약하자면 포인터를 사용하지 않는 함수를 정의할 경우 그걸
호출해 데이터를 전달할 수 있어요
포인터가 아니어야 해요
별표 포인터를 취하는 함수가 있다면
그걸 호출할 때 추가/하위
연산자로 호출해야 해요
주소를 보내 주셔야 해요
그게 구문이에요
이제 상수 키워드 사용으로 함수 매개 변수에 자격을 부여할 수 있어요
이 매개 변수에 대해 넘겨진 인수를 함수가 상수로 처리한다는 걸 나타내죠
매개 변수가 포인터일 때만 유용하죠
값을 전달할 때 포인터를 전달하지 않으면 함수 외부의 변화에
영향을 주지 않기 때문에 상관없어요 그걸
왜 상수로 하죠? 바꿔도 상관없잖아요
포인터 상수를 만드는 유일한 이유는 함수 값 바깥쪽이
변하는 걸 원치 않기 때문이죠
그래서 상수 키워드도 매개 변수에 적용할 수 있어요 바로 포인터죠
함수가 인수점의 값을 바꾸지 않을 거라는 걸 명시하기 위해서요
아주 중요하죠
이 예제에선 메시지 보내기 기능이 있어요 P 메시지 포인터가
필요해요
숯불 별 앞에 항상 키워드를 넣어요
이 형식의 매개 변수 p 메시지는 상수 문자에 대한 포인터예요
주소가 아니라 인격값이 변함없는 거예요
이 경우 우리가 하고 있는 건 손가락으로 가리키는 포인터는 바꿀 수 없어요
주소는 바꿀 수 있지만 값을 가리키는 건 바꿀 수 없어요
구문은 다른 포인터에서 상수를 만들 때와 비슷해요
상수 키워드는 제일 먼저 나타나는 거예요 그럼 값을 바꿀 수 없죠
포인터 자체는 상수라고 명시할 수 있지만
이건 말이 안 되죠 주소가 값으로 전달되니까요
호출 함수에서 렌더링 포인터를
바꿀 수 없어요 주소가 변경될 수 없도록 하려고 한다면 그게
무슨 소용이죠? 값으로 전달되니까요 특정 주소를 저장할
새 메모리 위치를
만드는 거죠 그러니 바꾼다고 해서 외부에서 바뀌는 건 아니죠
매개 변수를 상수로 만들고 싶을
뿐이죠 그게 가리키는 것의 값을 바꾸지 않게요
원본 포인터와 호출
기능은 어쨌든 못 바꿉니다 값을 통과하고 복사본을
통과하니까요
컴파일러는 상수 데이터에 대한 포인터인 인수가 안전하다는
걸 압니다 그래서 장점이 있죠 우연히 그 값이 가리키는 걸 변경할 순 없어요
함수 외부에 변화가 반영되는 걸 원치 않는다면 이걸 다시 할 수도 있어요
매개 변수의 인수로 상수 데이터에 포인터를 넘기면
매개 변수는 아까처럼 사용되어야 해요
함수를 호출해 상수에 넘기면 함수 선언은
상수 문자 포인터도 가져야 합니다 상수인
다른 포인터들처럼요
프로토타입과 일치하도록 정의해야 하죠
함수에서 포인터를 반환하는 거죠
함수에서 포인터를 반환하는 건 특별한 강력한 기능이죠
하나의 값만이 아니라 전체 값을 반환할 방법을 제공하죠
포인터의 또 다른 장점은 함수에서
더 많은 데이터를 리턴할 수 있다는 거예요
과거에는 값이 하나뿐이었어요
하지만 포인터는∙∙∙ 포인터는 아직 다루지
않은 구조를 가리킬 수도 있거든요 그 외 다른 것들도요 다양한
값을 리턴할 수 있죠 그러니 함수에
포인터를 전달하는 방법을 알았으니 이제 리턴 포인터에 관해
얘기할 거예요
포인터를 반환하는 함수를 선언해야 해요 함수 선언은 일치해야 하죠
아주 쉬워요 함수를 선언하거나 정의할 때 별표를
사용하면 돼요 그리고 그게 가리키는 포인터에 대한 return type을 갖는 거죠
그러니 주의하세요 포인터를 돌려보낼 때 발생하는 위험 요소들이 있으니까요
로컬 변수를 써서 인수가 가리키는 변수와 간섭하지 않게 하세요
포인터를 반환할 땐 다소 문제가 있어요 함수 안에서 포인터를
수정해 반환하면 의도치 않게
그렇게 될 수 있거든요
그러니 늘 로컬 변수를 쓰세요 인수가 가리키는 변수에 영향을
주고 싶지 않다면요
이번 강의에서는 함수에 포인터를
전달하고 함수에서 포인터를
리턴하는 법을 설명했는데요
함수에 포인터를 전달하는 이런 메커니즘을
사용함으로써 참조 전달을 시현하거나 모방합니다
주소에서 복사하니까요
주소를 복사할 때 그 주소로 쓸 경우 그 주소를 가리키는
게 뭐든 업데이트하게
됩니다 그 말은 사실상 함수 안의 데이터 값을 변경하면
함수 밖에서도 반영된다는 거죠
그걸 증명하기 위해 바꿔치기 방법을 사용하죠
아주 강력한 콘셉트예요 참조로 넘기기도 하고 포인터를 써서
참조할 수도 있고 함수 밖에서 뭔가를 바꾸고 싶을 때 그렇게 할 수도 있죠
고마워요