포인터에 대한 난해한 질문
/*************** 소스부분의 시작 *****************/
#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의 사이즈 만큼씩 차이가 나도록 주소값을
넣어주고 싶습니다.
그렇게 하려면 /** 주목 **/이라고 하는 부분을 어떻게 고쳐야 할까요?
고수님들의 현명한 가르침을 기대하겠습니다.
Re: 포인터에 대한 난해한 질문
포인터는 배열이 아닙니다...
포인터는 배열이 아니지만, []연산자를 쓸 수 있습니다.
흠... 제 생각이 틀리지는 않을 텐데요.
Re: 포인터에 대한 난해한 질문
*(char**)(*(*p + i) + j) = temp + i*row*size + j * size;;
Re: 이렇게 해보세요.
님의 소스중에 다음과 같은 부분이 있습니다.
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 라고 함수명을 혼동하여 정의 하셨네요.
아뭏든 수고 하세요. 컴파일해볼수있는 상황이 아니라 대충 눈으로보고 올
립니다.
그럼 이만..
답변 감사드립니다.....but...
결과는 달라지지 않는군요...쩝...
암튼 성의있는 답변 감사드립니다. 꾸벅
^ㅛ^.....
감사드립니다....그러나 core dump가 납니다.
이렇게 성의있게 답변해 주신 것 감사합니다.
그러나 님께서 추천하신 대로 하니 바로 core dump가 나는군요...
다른 묘안이 있으시면 현명한 가르침 부탁드립니다.
^^;
Re: 포인터에 대한 난해한 질문
김경태 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의 사이즈 만큼씩 차이가 나도록 주소값을
넣어주고 싶습니다.
그렇게 하려면 /** 주목 **/이라고 하는 부분을 어떻게 고쳐야 할까요?
고수님들의 현명한 가르침을 기대하겠습니다.
Re: 포인터에 대한 난해한 질문
음.. 전체적인 구조부터 살펴보니..
님이 메모리할당 개념에 약간 잘못생각하고 계신것이 있는것 같군요
그리고 가장큰문제는 메모리할당과 실제 사용과는 틀리게 사용한게
가장큰실숩니다.
님도 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
이것의 차이는 왜생기는지 이해 하시겠죠? 마찬가지원리겠죠...
이미 이것의 차이는 어떤형의 차이만큼 넘어가는게 아니라
포인터에 해당하므로 포인터 단위만큼넘어가게 되고 따라서 님이 할당한
번지에 제대로 도착할수 있습니다.
Re: 포인터에 대한 난해한 질문
어제 시간없이 답변드리다 보니 자세히 보지 못하고 답변드렸습니다. 그
래서 다시 답변드립니다.
>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를 위한 자료구조가 필요할 것 같습
니다.
아뭏든 자상한 가르침 너무 감사드립니다.
댓글 달기