포인터에 대한 난해한 질문

익명 사용자의 이미지

/*************** 소스부분의 시작 *****************/

#include

int arr_free(void ***);
int arr_malloc(int , int, int, void ***);

struct _a
{
char *arr;
int len;
};

typedef struct _a VARCHAR;

main()
{
int i, j;
VARCHAR **test;

arr_malloc(3, 2, 20 + sizeof(int), (void ***) & test);

for( i = 0; i < 3; i++)
for ( j = 0; j < 2; j++)
{
test[i][j].arr = (char *)&test[i][j];
printf("test[%d][%d] address is %d\n", i, j, &test[i]
[j]);

}

free_malloc((void ***) & test);
}

int arr_malloc(int col,int row,int size, void ***array)
{
int i = 0;
int j = 0;
char *temp;

if((*array = (void **)malloc(sizeof(int *) * col)) == NULL)
{
return -1;
}
if ((temp = (void *)malloc (size * col * row)) == NULL)
{
return -1;
}

for ( i = 0; i< col; i++ )
{
*(*(char ***)array + i) = temp + i*row*size;
printf("size %d, array temp + %d*%d is %d\n", size, i, row,
temp+i*row*s
ize);
/************* 주목! ******************/
for ( j = 0; j < row; j++ )
{
(*(*(char ***)array + i) + j) = temp + i*row*size + j *
size;
}
/***************************************/
}

return 0;
}

int free_malloc(void ***array)
{
free(**array);
free(*array);
return 0;
}

/************ 소스부분의 끝 *************************/

/************* 출력 결과 (주목부분 마킹처리) ******/

size 24, array temp + 0*2 is 134519040
size 24, array temp + 1*2 is 134519088
size 24, array temp + 2*2 is 134519136
test[0][0] address is 134519040
test[0][1] address is 134519048
test[1][0] address is 134519088
test[1][1] address is 134519096
test[2][0] address is 134519136
test[2][1] address is 134519144

/************** 출력결과의 끝 **********************/

/************** 컴파일 결과 (주목부분 열고) ********/
cc "varchar.c", line 60 error 1549 Modifiable lvalue required for
assignment operator.
/****************************************************/

1. 목적

보시면 아시겠지만, arr_malloc이란 함수는 모든 타입의 이차원 배열을
col, row, size of element(임의 타입)을 통하여 malloc하는데 그 목적
이 있습니다.

2. 문제점

출력결과를 보시면 아시겠지만,

test[i]의 주소값은 28 * 2만큼씩 즉 48만큼씩 가르키고 있으니 이상이
없습니다.

반대로,

test[i][j]의 주소값은 28 만큼씩 차이가 나는 것이 아니고, 처음에는
8만큼 후에는 40만큼씩 차이가 나므로 연속적인 주소공간의 배치를 생각
할때는 잘못된 주소를 가르키고 있음이 명백합니다.

그래서,

저는 /** 주목 **/이라는 부분을 통하여 &test[i][j]에다가 연속적인 주
소를 24만큼씩 차이가 나도록 assign하고 싶었습니다.

그런데,

컴파일을 하면 /** 컴파일 **/ 결과와 같이 수정가능한 왼쪽값(포인터값)
은 assignment operator가 필요하다고 합니다.

3. 질문

저는 위에서 의도한 대로 test[i]뿐만 아니라 test[i][j]도 일정한 간격
즉, malloc을 원하는 element의 사이즈 만큼씩 차이가 나도록 주소값을
넣어주고 싶습니다.

그렇게 하려면 /** 주목 **/이라고 하는 부분을 어떻게 고쳐야 할까요?

고수님들의 현명한 가르침을 기대하겠습니다.

익명 사용자의 이미지

포인터는 배열이 아닙니다...

익명 사용자의 이미지

흠... 제 생각이 틀리지는 않을 텐데요.

익명 사용자의 이미지


*(char**)(*(*p + i) + j) = temp + i*row*size + j * size;;

익명 사용자의 이미지

님의 소스중에 다음과 같은 부분이 있습니다.

for ( i = 0; i< col; i++ )
{
*(*(char ***)array + i) = temp + i*row*size;
printf("size %d, array temp + %d*%d is %d\n", size, i, row,
temp+i*row*s
ize);
/************* 주목! ******************/
for ( j = 0; j < row; j++ )
{
(*(*(char ***)array + i) + j) = temp + i*row*size + j *
size;
}
/***************************************/
}

위의 내용을 아래의 내용으로 수정하시면 될꺼에요.

for ( i = 0; i< col; i++ )
{
*((char **)array + i) = temp + i*row*size;
printf("size %d, array temp + %d*%d is %d\n", size, i, row,
temp+i*row*size);
/************* 주목! ******************/
for ( j = 0; j < row; j++ )
{
*(((char **)array + i) + j) = temp + i*row*size + j *
size;
}
/***************************************/
}

포인터 사용하시다가 잠깐 혼동이 있으셨는듯 합니다.

그리고 님께서 올리신 소스에 오류가 좀 많네요.

#include 도 하지 않으신 것부터 arr_free 라는 이름으로 함수
선언해놓고선
실제로는 free_malloc 라고 함수명을 혼동하여 정의 하셨네요.

아뭏든 수고 하세요. 컴파일해볼수있는 상황이 아니라 대충 눈으로보고 올
립니다.
그럼 이만..

익명 사용자의 이미지

결과는 달라지지 않는군요...쩝...

암튼 성의있는 답변 감사드립니다. 꾸벅

^ㅛ^.....

익명 사용자의 이미지

이렇게 성의있게 답변해 주신 것 감사합니다.

그러나 님께서 추천하신 대로 하니 바로 core dump가 나는군요...

다른 묘안이 있으시면 현명한 가르침 부탁드립니다.

^^;

익명 사용자의 이미지

김경태 wrote..
/*************** 소스부분의 시작 *****************/

#include <stdlib.h>

int arr_free(void ***);
int arr_malloc(int , int, int, void ***);

struct _a
{
char *arr;
int len;
}; 이 structure는 분명 크기가 8바이트죠?

아래에 계속~


typedef struct _a VARCHAR;

main()
{
int i, j;
VARCHAR **test;

arr_malloc(3, 2, 20 + sizeof(int), (void ***) & test); 이 함수에는 structure크기가 24인 것으로 넘깁니다..


for( i = 0; i < 3; i++)
for ( j = 0; j < 2; j++)
{
test[i][j].arr = (char *)&test[i][j];
printf("test[%d][%d] address is %d\n", i, j, &test[i]
[j]); 여기서!!! test[i][j]는 결국 *(test[i]+j)인데, test[i]는 VARCHAR *형이
죠?

근데 위에서 VARCHAR형은 크기가 8바이트이므로 *(test[i]+j)는 결국

test[i]값에 8*j (24*j가 아님)이 더해집니다..

또한 /** **/ 부분 전혀 필요없고 문제는 단지 이겁니다..

단순히 VARCHAR형의 크기를 24로 만들어주시던지 아니면 arr_malloc에

정직하게(?) size인자에 8을 넘겨주시던지 하면 됩니다.

}

free_malloc((void ***) & test);
}

int arr_malloc(int col,int row,int size, void ***array)
{
int i = 0;
int j = 0;
char *temp;

if((*array = (void **)malloc(sizeof(int *) * col)) == NULL)
{
return -1;
}
if ((temp = (void *)malloc (size * col * row)) == NULL)
{
return -1;
}

for ( i = 0; i< col; i++ )
{
*(*(char ***)array + i) = temp + i*row*size;
printf("size %d, array temp + %d*%d is %d\n", size, i, row,
temp+i*row*s
ize);
/************* 주목! ******************/
for ( j = 0; j < row; j++ )
{
(*(*(char ***)array + i) + j) = temp + i*row*size + j *
size;
}
/***************************************/
}


return 0;
}

int free_malloc(void ***array)
{
free(**array);
free(*array);
return 0;
}

/************ 소스부분의 끝 *************************/

/************* 출력 결과 (주목부분 마킹처리) ******/

size 24, array temp + 0*2 is 134519040
size 24, array temp + 1*2 is 134519088
size 24, array temp + 2*2 is 134519136
test[0][0] address is 134519040
test[0][1] address is 134519048
test[1][0] address is 134519088
test[1][1] address is 134519096
test[2][0] address is 134519136
test[2][1] address is 134519144

/************** 출력결과의 끝 **********************/

/************** 컴파일 결과 (주목부분 열고) ********/
cc "varchar.c", line 60 error 1549 Modifiable lvalue required for
assignment operator.
/****************************************************/

1. 목적

보시면 아시겠지만, arr_malloc이란 함수는 모든 타입의 이차원 배열을
col, row, size of element(임의 타입)을 통하여 malloc하는데 그 목적
이 있습니다.

2. 문제점

출력결과를 보시면 아시겠지만,

test[i]의 주소값은 28 * 2만큼씩 즉 48만큼씩 가르키고 있으니 이상이
없습니다.

반대로,

test[i][j]의 주소값은 28 만큼씩 차이가 나는 것이 아니고, 처음에는
8만큼 후에는 40만큼씩 차이가 나므로 연속적인 주소공간의 배치를 생각
할때는 잘못된 주소를 가르키고 있음이 명백합니다.

그래서,

저는 /** 주목 **/이라는 부분을 통하여 &test[i][j]에다가 연속적 인 주
소를 24만큼씩 차이가 나도록 assign하고 싶었습니다.

그런데,

컴파일을 하면 /** 컴파일 **/ 결과와 같이 수정가능한 왼쪽값(포인터 값)
은 assignment operator가 필요하다고 합니다.

3. 질문

저는 위에서 의도한 대로 test[i]뿐만 아니라 test[i][j]도 일정한 간격
즉, malloc을 원하는 element의 사이즈 만큼씩 차이가 나도록 주소값을
넣어주고 싶습니다.

그렇게 하려면 /** 주목 **/이라고 하는 부분을 어떻게 고쳐야 할까요?

고수님들의 현명한 가르침을 기대하겠습니다.

익명 사용자의 이미지

음.. 전체적인 구조부터 살펴보니..

님이 메모리할당 개념에 약간 잘못생각하고 계신것이 있는것 같군요

그리고 가장큰문제는 메모리할당과 실제 사용과는 틀리게 사용한게

가장큰실숩니다.

님도 aaa[x][y] 이것이 어떠한원리에의해 번지가 계산되는지는 알고 계시
죠?

위의 타입에의해 x y 의 계산에 의해 번지수가 결정되는것입니다

그렇다면..타입에의존 따라서 당연히
test[0][0] address is 134519040
test[0][1] address is 134519048
이것의 출력결과가 나온다는걸 아시겠죠. 또한 나올수 밖에 없겠죠?
님이 주목이라고 한부분을 아무리 수정해봐도 이것이 변하진 않습니다.
전체적인 구조를 손봐야 할것같내요.
그러면..
test[0][1] address is 134519048
test[1][0] address is 134519088
이것의 차이는 왜생기는지 이해 하시겠죠? 마찬가지원리겠죠...
이미 이것의 차이는 어떤형의 차이만큼 넘어가는게 아니라
포인터에 해당하므로 포인터 단위만큼넘어가게 되고 따라서 님이 할당한
번지에 제대로 도착할수 있습니다.

익명 사용자의 이미지

어제 시간없이 답변드리다 보니 자세히 보지 못하고 답변드렸습니다. 그
래서 다시 답변드립니다.

>test[i][j]의 주소값은 28 만큼씩 차이가 나는 것이 아니고, 처음에는
>8만큼 후에는 40만큼씩 차이가 나므로 연속적인 주소공간의 배치를 생각
>할때는 잘못된 주소를 가르키고 있음이 명백합니다.

잘못된 것이 아닙니다. 컴퓨터는 정직합니다.^^
님의 소스 내용중
if((*array = (void **)malloc(sizeof(int *) * col)) == NULL)
라는 라인부터 시작하여 메모리 할당되는 부분의 내용을 검토해보세요.
메모리 할당은 잘하셨지만, 메모리 할당과 관련되어 잘못이해하고 계시는
듯합니다. 메모리 할당부분을 그림으로 한번 그려보시면 어떤부분을 혼동
하고 계신지 쉽게 찾을수 있을 것입니다.

>저는 /** 주목 **/이라는 부분을 통하여 &test[i][j]에다가 연속적인 주
>소를 24만큼씩 차이가 나도록 assign하고 싶었습니다.

님이 사용하시는 방법으로는 절대로 그렇게 안됩니다. 이유는 위의 내용
과 동일합니다.
처음부터 array에다가 한꺼번에 연속적인 메모리 주소를 할당하지 않는
이상 불가능합니다. 확률에 의존해야 합니다.^^

>컴파일을 하면 /** 컴파일 **/ 결과와 같이 수정가능한 왼쪽값(포인터
값)
>은 assignment operator가 필요하다고 합니다.

상수와도 같은 주소값에다가 할당연산자를 사용하여 값을 넘기려고 해서
그런 것입니다.

>저는 위에서 의도한 대로 test[i]뿐만 아니라 test[i][j]도 일정한 간격
>즉, malloc을 원하는 element의 사이즈 만큼씩 차이가 나도록 주소값을
>넣어주고 싶습니다.
>그렇게 하려면 /** 주목 **/이라고 하는 부분을 어떻게 고쳐야 할까요?

님께서 원하시는 내용을 구현하기 위해선 /** 주목 **/이라고 표시하신
부분만 고친다고
그렇게 될수 없습니다. 메모리 할당부분을 전면 수정해야 합니다.
array에 한번에 연속적인 메모리 주소들을 할당하는 방법밖에 없습니다.

익명 사용자의 이미지

일단 중요한 것은

*(*array + i) + j가 상수라는 거죠...

그리고 그 상수는 대상의 type에 따라서 컴파일러가 계산해준다는 겁니다.

좋은 가르침 감사드립니다.

익명 사용자의 이미지

arry[0][0]과
arry[0][1]과의 차이와,

arry[0][1]과
arry[1][0]의 차이를 이제야 알겠군요.

이 문제를 해결하려고 한다면,

결국,

arry[i][j]각각을 담을 또하나의 자료구조(pointer type)을 두는 수밖에
는 없겠군요.

아뭏든 좋은 가르침 감사드립니다.

익명 사용자의 이미지

님의 말씀대로 아예,

arry의 element의 size를 정하는 경우에는,
arry[i]+j의 포인터 연산이 type에 의해서 지정되어 지므로 결국,
제 프로그램은 제대로 돌아가게 되겠죠.

arry의 한 원소인 arr의 길이가 가변일 수 있다고 한다면,
그게 맞는 솔루션인것 같습니다.

만약에 억지로 arry의 크기를 일정하게 한다면 또하나의 자료구조 즉,
arry[i][j]의 주소를 담을 pointer를 위한 자료구조가 필요할 것 같습
니다.

아뭏든 자상한 가르침 너무 감사드립니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.