자주 쓰이는 용도로, memory allocation 을 defer 하는 경우 입니다.
caller 에서 어떠한 이유로 ( size 를 결정할수 없다던지, 등등.. ) malloc 을 할수 없었다면, pointer variable 의 주소를 넘겨줘서, callee 에게 malloc 을 시킬수 있습니다.
sqlite 에서 connection 을 그렇게 넘겨줬던것 같네요. open 함수 에서 그렇게 했네요.
사실 포인터는 깊이가 깊어지면 질수록 코드를 이해하기 더 복잡해지고,
최종적인 값을 참조하려면 포인터 수만큼 점프해서 접근해야 하기 때문에
부하가 생길 수밖에 없을 것 같습니다.
저도 사실 포인터 세개 이상은 거의 써본 적이 없네요...
하지만 컴파일러의 특성때문에 가끔 편법으로 사용하는 경우는 있습니다.
예를 들면, 표준에서 volatile 키워드는, 키워드로 지정된 변수에 접근할 때,
cache를 이용하지 않고 직접 메모리로 접근하여 읽도록 해주는 키워드입니다.
하지만 컴파일러마다 이 키워드에 대한 지원이 달라서, 컴파일러 마다 동작하는 방식이
틀려질 수 있기 때문에, volatile의 의미를 보장해 주기 위해서 일부러 포인터를 여러 겹으로
꼬아서 항상 메모리로 접근해서 변수의 내용을 읽어들이게 하는 편법을 쓸 때도 있는 것 같습니다.
포인터를 갱신하기 위해서 사용합니다.
수학 계산 용도가 아니라면 일반적으로 포인터의 포인터는 외부 포인터 변수의 주소를 갱신하기 위해 사용합니다. 아래의 예에서는 전역 변수를 대상으로 잡았지만 일반적으로는 동적 할당된 변수의 주소를 바꾸어 주는 용도로 사용합니다.
bar 함수를 이렇게
bar 함수를 이렇게 하는건 안될까요?
그래서 호출할 때는 포인터의 포인터 대신에 포인터를 넘겨서
넘긴 포인터 자체를 변경시키는 식으로는 안되나요?
int *ptr이 지역 변수이므로 foo 함수의 x 변수에는 변화가 없습니다.
지역 변수에 값을 대입하면 지역변수의 scope를 벗어날 때 값이 사라집니다.
당연히 ptr의 값을 갱신하는 것은 무의미한 것이 됩니다.
(원래 코드에서는 포인터 참조를 통해 x 변수에 직접 값을 대입한 것입니다)
실제로 위의 코드를 컴파일 해서 돌려 보면 결과가 다르다는 것을 쉽게 확인할 수 있을겁니다.
위와 같이 하시면
위와 같이 하시면 아래와 같은 결과라고 생각하시면 됩니다.
void bar(int ptr)
{
ptr = z;
}
void foo(void)
{
int x = y;
bar(x);
/* x == &z, z = 100 */
*x = 100;
printf("y = %d, z = %d\n", y, z);
}
함수 / 포인터 관련 내용을 살펴보시는게 도움이 되지 않을까 합니다.
자주 쓰이는 용도로,
자주 쓰이는 용도로, memory allocation 을 defer 하는 경우 입니다.
caller 에서 어떠한 이유로 ( size 를 결정할수 없다던지, 등등.. ) malloc 을 할수 없었다면, pointer variable 의 주소를 넘겨줘서, callee 에게 malloc 을 시킬수 있습니다.
sqlite 에서 connection 을 그렇게 넘겨줬던것 같네요.
open 함수 에서 그렇게 했네요.
삽질의 대마왕...
삽질의 대마왕...
간단하게
간단하게 생각하세요. (함수 인자로 전달해서) 뭔가를 변경하고 싶으면 그 뭔가에 대한 포인터를 전달합니다.
변수를 변경하려면 변수에 대한 포인터 (*),
포인터를 변경하려면 포인터에 대한 포인터 (**),
포인터의 포인터를 변경하려면 포인터의 포인터에 대한 포인터 (***),
......
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
깔끔하네요 :) 혹시,
깔끔하네요 :)
혹시, ***p 에대한 use case 가 뭐가 있을까요?
2차원 배열의 pointer 를 넘겨주기 정도쯤 될까요?
삽질의 대마왕...
삽질의 대마왕...
***p 형태는 예전에
***p 형태는 예전에 커널 소스쪽에서 본거는 같은데...
뭐하는 놈이었는지는 잘 기억 안나네요.
C는 손 놓은지 10년 가까이 되서... 실제로 제가 직접 프로그래밍할 때는 포인터에대한 포인터(**) 정도 까지만 썼던 것같습니다.
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
-----
오늘 나의 취미는 끝없는, 끝없는 인내다. 1973 法頂
전 C 언어 학교
전 C 언어 학교 숙제에서 문자열의 동적 배열을 함수로 넘겨서 고칠 때(동적 배열이라 배열의 시작 주소가 바뀔 수도 있음) (char***) 형을 쓴 적이 있습니다.
포인터는...
사실 포인터는 깊이가 깊어지면 질수록 코드를 이해하기 더 복잡해지고,
최종적인 값을 참조하려면 포인터 수만큼 점프해서 접근해야 하기 때문에
부하가 생길 수밖에 없을 것 같습니다.
저도 사실 포인터 세개 이상은 거의 써본 적이 없네요...
하지만 컴파일러의 특성때문에 가끔 편법으로 사용하는 경우는 있습니다.
예를 들면, 표준에서 volatile 키워드는, 키워드로 지정된 변수에 접근할 때,
cache를 이용하지 않고 직접 메모리로 접근하여 읽도록 해주는 키워드입니다.
하지만 컴파일러마다 이 키워드에 대한 지원이 달라서, 컴파일러 마다 동작하는 방식이
틀려질 수 있기 때문에, volatile의 의미를 보장해 주기 위해서 일부러 포인터를 여러 겹으로
꼬아서 항상 메모리로 접근해서 변수의 내용을 읽어들이게 하는 편법을 쓸 때도 있는 것 같습니다.
_________________________________________________________
nineye's blog
포인터의 포인터에 대해서
2중포인터는 보통 2차원배열을 넘길때 사용합니다
참고로
1차원배열은 *ptr
2차원배열은 **ptr
3차원배열은 ***ptr
불필요한 메모리를 사용하지않고 처리속도도 빠르게 처리할수있지요.
이렇게 포인터로 넘겨주면 바로 배열의 특정값을 변경이 가능하고
배열의 특정위치를 포인터 어드레스로부터 계산해서 접근이가능하기 때문입니다
*(ptr+8)이런식으로요..
임베일디드환경이라든지 시스템처리에서 메모리를 많이 사용하는경우에 메모리사용을 억제하지요
방가워요
설마 f(int a[])를
설마 f(int a[])를 호출하면 a가 복사되어 넘어간다고 생각하시는 겁니까?
제가 잘못 이해한 거라면 다행이겠지만요.
Real programmers /* don't */ comment their code.
If it was hard to write, it should be /* hard to */ read.
배열의 구현은 그냥 *ptr로 됩니다.
2차원이건 n차원이건 말이죠. 논리적으로 그렇단 얘기지 배열이란 것 자체가 연속된 메모리 공간을 전제로 합니다.
int a[3][4] ;
for(int i= 0 ; i < 3 ; ++i)
{
for(int j= 0 ; j < 4 ; ++j)
{
a[i][j]= 0 ; // *(a + i * 4 + j)= 0 ; 과 동일
}
}
댓글 달기