
🖐🏻 포인터 공부를 하기 전에,
CTO님께서 휴일에 뭘 하셨냐고 물어보셔서 얕은 복사와 깊은 복사를 공부했다고 말씀드리니, C언어의 포인터를 공부해보면 더 이해가 쉬울 것이라고 말씀을 해주셔서 포인터와 함께 불금을 보냈다. 하하! C언어에서의 포인터가 뭐길래 이걸 공부해보라고 말씀해주신건지 이해해보려고 부단히 노력했던 것들에 대한 기록을 남겨보자…
📝 데이터 타입
원시 타입
- 실제 데이터의 값을 저장하는 타입
참조 타입
- 메모리 번지 값을 통해 객체를 참조하는 타입
👉🏻 포인터란?
📝 포인터와 메모리 주소
포인터
- 변수의 메모리 주소를 가리키는 변수
메모리 주소
메모리 위치에 대한 식별자로, 컴퓨터 프로그램이나 하드웨어 장치가 데이터를 저장하고 나중에 이를 가져오는 장소
해당 데이터가 저장된 메모리의 시작 주소
📝 포인터에 대해 더 알아보자
- 메모리의 주소값을 저장하는 변수 (포인터 변수)
int n = 100; // 변수 선언
int *ptr = &n; // 포인터 선언
/*
n 이라는 변수를 선언하고 변수는 100 이라는 값을 가짐
ptr 이라는 포인터는 n의 주솟값을 참조함...
개섹시하다 근본 언어라 그런걸까
*/
🧮 포인터 연산자
📝 포인터 연산자의 종류
주소 연산자 :
&참조 연산자 :
*
📝 주소 연산자 ( & )
변수의 이름 앞에 사용, 해당 변수의 주소값을 반환
&기호는 앰퍼샌드라고 읽으며, 번지 연산자로고도 불림
📝 참조 연산자 ( * )
포인터의 이름이나 주소 앞에 사용하여, 포인터에 가리키는 주소에 저장된 값을 반환
기호의 사용 위치에 따라 다양한 용도로 사용됨
이항 연산자로 사용하면 곱셈 연산으로 사용
포인터 선언 시나 메모리에 접글할 때도 사용됨
🙋🏻♀️ 포인터 선언
타입* 포인터이름;
타입 : 포인터가 가리키고자 하는 변수의 타입을 명시
포인터 이름 : 포인터가 선언된 후 포인터에 접근하기 위해 사용됨
type* ptr = &variable;
type* ptr = 주소값;
👀 포인터 참조
포인터는 참조 연산자를 사용해 참조가 가능함
[ 예제 ] 포인터의 주소값과 함께 포인터가 가리키고 있는 주소값의 데이터를 참조
int x = 7; // 변수 선언
int *ptr = &x; // 포인터 선언
int *pptr = &ptr; // 포인터 참조
/*
x 라는 변수를 선언하고 7이라는 값을 할당 ( 0x12 )
ptr 이라는 포인터는 x의 주소의 주소값을 반환 ( 0x12 )
pptr 이라는 포인터는 x의 주솟값이 저장된 주소값을 반환 ( x의 주소값 )
*/
int num = 123;
int* num_address = #
printf("%p", &num);
printf("%p", num_address);
printf("%p", &num_address);
printf("%d", *num_address);
/*
int형 num 값이 저장된 주소값을 가리키는 포인터 num_address
"%p", 0x00DF0213 : 123이 저장된 주소값 반환
"%p", 0x00DF0213 : num_address = &num
"%p", 0x00FA0255 : 0x00DF0213이 저장된 주소값 반환
"%d", 123 : num_address에 저장된 주소값에 저장된 값을 반환
*/
int num01 = 1234;
double num02 = 3.14;
int* ptr_num01 = &num01;
double* ptr_num02 = &num02;
/*
num01 은 1234 를 가짐 (대충 &7번방)
num02 는 3.14 를 가짐 (대충 &8번방)
ptr_num01 => &7
ptr_num02 => &8
*/
👩🏻💻 자바크스립트에서의 pointer
자바스크립트를 공부를 하고 있는데, C언어에서의 pointer 를 공부해보라고 말씀을 해주신 것에는 그만한 이유가 있으실 것이라 생각을 해서 그 이유를 찾아보려고 포인터의 관점(?) 에서 다시 한번 JavaScript 의 깊은 복사, 얕은 복사를 바라보려고 해봤다.
📝 원시 타입에서의 복사
let dobby = "is Free";
let leetrue = dobby;
console.log(leetrue); // "is Free";
dobby = "is not Free!";
console.log(leetrue); // "is Free";
console.log(dobby); // "is not Free!";
원시 타입의 경우에는 실제 데이터의 값 자체를 저장하기 때문에 leetrue 라는 변수는 dobby 라는 변수가 복사 당시 가지고 있단 "is Free" 라는 데이터 값 자체의 주소를 저장하게 된다. 따라서 dobby 변수의 값이 새로 할당이 되었다고 하더라도 dobby 변수가 가지고 있는 데이터 주소만 달라질 뿐, leetrue 는 여전히 자유인 상태이다.
📝 참조 타입에서의 복사
let dobby = {
isFree : true,
};
let leetrue = dobby;
console.log(leetrue);
leetrue.isFree = false;
console.log(leetrue); // { isFree : false }
console.log(dobby); // { isFree : false }
let dobby = {
isFree : true,
};
let leetrue = dobby;
console.log(leetrue);
dobby.isFree = false;
console.log(leetrue); // { isFree : false }
console.log(dobby); // { isFree : false }
참조형의 경우에는 이야기가 달라진다. 참조형은 데이터의 값 자체가 아닌 메모리 번지 값을 통해 객체를 참조하기 때문에 leetrue 라는 변수는 dobby 라는 변수의 데이터 주솟값을 참조한다. 따라서 dobby 의 데이터 또는leetrue 변수에 값을 조작을 한다면 두 변수는 같은 주소를 바라보고 있기 때문에 모두의 값이 바뀌어 보이게 된다.
📝 그래서 pointer 는 왜 공부했을까..
사실 CTO님의 의도를 명확하게 이해한 것은 아니지만 나름 이해를 하려고 노력했던 건 결국은 JavaScript 에서 얕은 복사라고 불리는 것이 곧 포인터의 개념을 따라가고 있는 것이라는 생각이 들었다. JavaScript 에 이런 문법은 없겠지만, C언어의 포인터 개념으로 JavaScript 코드를 작성한다면,
/* JavaScript의 얕은 복사(참조 복사) */
let dobby = {
isFree : true,
};
let leetrue = dobby; // leetrue 변수는 dobby의 주솟값을 참조한다.
/* Pointer의 개념으로 바라봤을 때,
- 아래와 같은 문법은 존재하지 않고, C언어 포인터와 참조 연산자를 자바스크립트에 대입해봤을 뿐임
*/
let dobby = {
isFree : true,
};
let* leetrue = *dobby; // leetrue 는 dobby 라는 변수의 주솟값에 담긴 값을 참조
위와 같이 leetrue 라는 포인터 변수가 dobby 의 주솟값이 가지고 있는 데이터의 주솟값을 참조해 저장하고 있는 모습이 아닐까? 라고 생각을 해봤다. 그렇기 때문에 dobby 의 값이 바뀌게 된다면 leetrue 는 이를 참조하고 바라보고 있기 때문에, 함께 값이 바뀐 것으로 확인이 되는 것 같다.
💜 결론
너무 답답해서 CTO 님께 오밤중에 내가 이해한 것이 CTO님께서 의도하신 바와 방향이 맞는지 여쭤보는 장문의 슬랙을 남겼는데, 얼른 답을 받고 싶다. 그게 아니라면 새로운 무언가를 또 얻을 수 있을 것이고 이게 맞았다면 뭔가 뿌듯하게 불금을 마무리한 느낌에 기분이 참 좋을 것 같다!
C언어는 처음이었는데 근본 언어는 뭔가 다르구나 싶기도하고..? 🤔 ㅋㅋㅋ 나중에 또 키워드를 얻는다면 더 공부를 해봐야겠다! 오늘은 이만 마무리!
👩🏻💻 후일담…
어제 CTO님께 질문드렸던 것에 대한 답변을 받았다. 참조형이 무엇인지 이해하는데 포인터의 개념이 도움이 될 것이라고 생각이 되셔서 이야기를 해주셨다고..! 주소를 갖는 변수라는 것이 프로그래민에서 왜 필요한가에 대해 가장 많은 레퍼런스를 갖는게 포인터여서 좋을 것 같아서 추천을 해주셨던!
추가로 포인터에서 메모리 릭이 왜 많이 발생하는지에 대해 한 번 찾아보고 이러한 릭을 어떻게 없애려고 하는지 보면 좋을 것 같다고 이야기를 해주셔서 이번엔 이 부분에 대해 공부를 해볼까 싶다. 좋아좋아 파이튕
![[월간 이트루] 3월의 회고.](https://cdn.hashnode.com/res/hashnode/image/upload/v1711895194426/f6a22b40-ffd3-4b11-a25b-e1b040b11853.png)
![[월간 이트루] 2월의 회고.](https://cdn.hashnode.com/res/hashnode/image/upload/v1709129901980/5a2af3c5-8f6e-4f07-9c4f-1b43bef27ae9.png)


![[월간 이트루] 1월의 회고.](https://cdn.hashnode.com/res/hashnode/image/upload/v1706708547437/51af577d-21f9-4256-8939-95c577a58abc.jpeg)