C 이중포인터에 대한 질문

wcg0112의 이미지

void abc(char **a);

int main(void)
{
char *name;
abc(&name);
printf("%s\n",name);
return 0;
}

void abc(char **a)
{
*a=(char*)malloc(100);
scanf("%s",*a);

}

정상적 예문이구요

'같은 코드 일것이다' 라고 생각한 제 코드입니다

void abc(char *a);

int main(void)
{
char *name;
abc(name);
printf("%s\n",name);
return 0;
}

void abc(char *a)
{
a=(char*)malloc(100);
scanf("%s",a);

}

뭐가 다른건가요...(물론 밑에건 실행시 에러가 발생...)

한참 배우는 중이라 포인터 개념이 많이 부족합니다.

너무 답답해서 여러군데 찾아봣지만

원하는 답변을 구할수가 없네요.

요약을 하자면.
함수 인자 전달시 왜 더블포인터를 사용하는가? 입니다(배열 제외하구요)
예문이 적절한지 모르겠네요.
저 둘의 차이점이 궁금합니다.

mr.lee의 이미지

호출자의 변수를 (포인터든 일반 변수든..) 함수에 인자로 넘겨서 변수의 값 (포인터라면 포인터가 가리키고 있는곳의 값) 을 바꾸고자 할때는 변수의 값이 아닌 변수의 주소를 넘겨줘야 겠죠. int a 도 &a 를 char* b도 &b 를 넘기는거죠. 다만 받는쪽에선 &a를 받으면 (int)* 로 받는것이고 &b를 받는것은 (char*)* 로 받는것일뿐.

포인터 변수를 주소가 아닌 값으로 넘기고 받으면 포인터변수가 실제 가리키는곳의(포인터 변수값이 주소인곳) 수정을 하는것이 아니라 포인터 변수 그 자체가 저장된 곳이 수정되어 버리죠. 포인터 변수 그 자체는 '주소크기' 만 차지하죠 32비트 머신이면 32비트 (4byte) 64비트 머신이면 64비트 (8byte)

crimsoncream의 이미지

C언어 관련 설명 중에서 call by value만 가능하고 call by reference가 지원되지 않아 pointer를 이용해서 같은 효과를 낸다. 라는 류의 설명을 찾아서 보시면 이해가 되시리라 생각합니다.
딱 적합한 텍스트는 아니지만 여기서 차이를 알아 보십시요.
http://en.wikipedia.org/wiki/Call_by_value#Call_by_value

------------------------------------------------------------------------
오늘 우리는 동지를 땅에 묻었습니다. 그러나 땅은 이제 우리들의 것입니다.
아직도 우리의 적은 강합니다. 그러나 우리는 그들보다 많습니다.
항상 많을 것입니다.

오늘 우리는 동지를 땅에 묻었습니다. 그러나 땅은 이제 우리들의 것입니다.
아직도 우리의 적은 강합니다. 그러나 우리는 그들보다 많습니다.
항상 많을 것입니다.

ㅡ,.ㅡ;;의 이미지

님이 편지봉투에 쓰인주소를 지우고 새주소(메모리할당)를 쓰고 싶은데.. 친구에게 편지봉투에 적힌 현제의 주소(내용)를 알려주면될까요..

편지봉투 자체(포인터)를 건네 줘야할까요.. ㅡ,.ㅡ;

----------------------------------------------------------------------------
C Library Development Project


----------------------------------------------------------------------------

노아의 이미지

int main(void)
{
char *name;
printf("[%p] \n", name);
abc(name);
printf("%s\n",name);
return 0;
}

void abc(char *a)
{
a=(char*)malloc(100);
printf("[%p] \n", a);
scanf("%s",a);
}

이렇게 해보면 왜 그런지 정확하게 알수 있을것 같군요.
기본적으로 c에서 함수를 호출하기전에 local변수는 모두 스택에 저장이 되고, 호출된 함수에서 발생하는 모든 변수도 스택에 저장하게
됩니다. 그리고 그 함수에서 return하게 되면 스택에서 pop을 하게 되죠. 그래서 c에서 call by value를 지원하게 됩니다.
call by reference를 지원하지 않는 이유 입니다.

ㅡ,.ㅡ;;의 이미지

그건 아니라고 봅니다.
개념적으로 생각해야죠..
더구나 위의예로 call by reference 가 아니란건 더이상하군요.
오히려 이중 call by reference기 때문에... 라고 해야 맞다고봅니다...
따라서 이중 포인터를 써야함은 당연하죠..
더구나 여타언어에서 call by reference 를 지원한다해도 그이상도 되지 않는다는겁니다.
오히려 이중 삼중 레퍼런스를 구현할수 있는건 바로 C의 특징이기도 하죠..

----------------------------------------------------------------------------
C Library Development Project


----------------------------------------------------------------------------

emptysky의 이미지

두번째 코드의 경우 포인터 자체도 변수이기 때문에
포인터 주소만을 복사하겠죠..
근데 문제는 복사받은 포인터 주소가 아무짝에 쓸모없는 쓰레기 값을
가지고 왔다는 것입니다.
물론 그걸 또 다시 힙주소(malloc)로 덮어쓰는데 그 주소를 리턴시켜 받지않는한 의미가 없죠..
(a 가 로컬 포인터 변수이기 때문에 함수종료시 스택에서 사라집니다.)

두번째 코드에서 name 을 넘겨주기전에
name = (char*)malloc(100);
한줄 추가하시면 되겠네요

void abc(char *a);
 
int main(void)
{
  char *name;
  name = (char*)malloc(100);
  abc(name);
  printf("%s\n",name);
  return 0;
}
 
void abc(char *a)
{
// a = (char*)malloc(100);
   scanf("%s",a);
 
} 

『 아픔은.. 아픔을 달래줄 약이 무엇인지 알면서도 쓰지 못할 때 비로소 그 아픔의 깊이를 알수가 있음이다. 』
『 for return...』

『 아픔은.. 아픔을 달래줄 약이 무엇인지 알면서도 쓰지 못할 때 비로소 그 아픔의 깊이를 알수가 있음이다. 』
『 for return...』

sunyzero의 이미지

reentrant 를 공부해보시면 쉽게 이해할 수 있을겁니다.
그 외에는 쓰레드에서도 pthread_join() 에서 이중 포인터를 사용합니다.

예를 들어 김대리가 예전에 만든 함수 char *myfunc1(const char *src) 가 있다고 가정합시다.
이 함수는 char * 의 형을 리턴값으로 사용하는데, 실패시에는 NULL 을 리턴합니다.

그런데 실패 시에 실패 코드도 같이 리턴해야 한다고, 김과장이 바꾸라고 하네요.
힘없는 김대리, 당연히 고쳐야겠죠?
(참고로 대부분의 reentrant 함수가 이런 식으로 변경되어 디자인되어있습니다)

그래서 기존 리턴값인 char * 는 포인터로 돌려주고,
새로운 함수에서는 리턴값은 int 형으로 성공시 0, 실패시 음수, 에러시 양수를 리턴하도록 바꿉니다.

그래서 김대리는 int myfunc2(char *dest, const char *src) 으로 바꾸었습니다.
그런데 이건 틀린 변환입니다.
왜냐하면 함수가 실패하면 dest 에 NULL 을 채울텐데 그러면 주소를 잃어버리죠?
따라서 이중 포인터가 사용되어 int myfunc2(char **dest, const char *src) 가 되어야 맞습니다.

즉 주소값을 리턴하는 함수에서 리턴값을 매개변수쪽으로 이동시킬때
그 주소값을 리턴해야 한다면 주소의 포인터가 되므로 이중 포인터가 됩니다.

이외에 매트릭스가 필요해서 이중포인터를 사용하기도 하는데, 그것보다는 위의 예가 더 이해하기는 편할겁니다.
========================================
* 부분이 전체를 대변하는 하나의 속성일때 진리이다.
영속적이지 못한 것은 전체가 될 수 없다.

========================================
* The truth will set you free.

ㅡ,.ㅡ;;의 이미지

그럼 김과장이 문제로군요..ㅡ,.ㅡ;;

----------------------------------------------------------------------------
C Library Development Project


----------------------------------------------------------------------------

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.