포인터 공부중입니다. 될꺼같은데, 세그먼트폴트가 납니다. ㅜㅜ; 한번 봐 주세요.
글쓴이: sia79 / 작성시간: 수, 2007/02/14 - 4:36오후
#include<stdio.h> #include<stdlib.h> int haha( char* test2[] ) ; int main(void) { int i=0; char* a; haha ( a ) ; for(i; i<3; i++ ) printf("%s\n", a[i] ) ; return 0; } int haha( char* test2[] ) { printf("<<< haha START >>>\n"); test2 = (char * ) malloc( sizeof(char *) * 3 ) ; test2[0] = (char *) malloc( sizeof(char) * 5 ) ; test2[1] = (char *) malloc( sizeof(char) * 5 ) ; test2[2] = (char *) malloc( sizeof(char) * 5 ) ; memcpy( &test2[0] , "AAAA" , 5 ) ; memcpy( &test2[1] , "BBBB" , 5 ) ; memcpy( &test2[2] , "CCCC" , 5 ) ; printf("<<< haha END >>>\n"); return 0; }
haha라는 함수에서는 포인터 배열을 완성시켜서 메인에 그 주소를 넘겨줍니다. haha함수에서 문자열은 일단 고정이지만 가변이 될 꺼구요.
메인에서 이 포인터를 이용해서 haha에서 완성된 문자들을 이용(인쇄)하고 차례차례 프리 시켜주려고합니다만.
세그먼트 폴트 에러를 못 잡겠습니다.
test2 = (char * ) malloc( sizeof(char *) * 3 ) ; 가 char* test2[3]; 과 같게 만들려고 한건데... 제대로 된건가요?
또, malloc함수가 지금 haha에 있는데, 그 함수 벗어나서 메인에 가면 사라진다는데, 값 유지 하려면 전역으로 해야하나요?
Forums:
memcpy( *test2[0] , "AAAA" ,
memcpy( *test2[0] , "AAAA" , 5 ) ; &test2[0]이런식으로 &가 와야하지 않나요?
memcpy( *test2[1] , "BBBB" , 5 ) ;
memcpy( *test2[2] , "CCCC" , 5 ) ;
memcpy( *test2[3] , "DDDD" , 5 ) ;
아... &군요. 지금
아... &군요.
지금 형태에서 test2[0]을 역참조해도 주소라고 생각했는데... 이상하네요;
그런데도 여전히... 폴트 ...
포인트 초기화를 안
포인트 초기화를 안 하셨네요.
처음이 이상한거 같습니다.
제가 완성한 코드는 다음과 같습니다.
악. 갑자기 별
악. 갑자기 별 세개짜리 보고 놀랐습니다. 제가 만든 것은 정말 엉망이었군요.
어렵네요. 몇가지 더 답변을 받고 싶습니다.
다른 함수에서 선언한 malloc은 꼭 그 함수에서 프리를 시키거나 다른 함수로 연결해서 가지고 가면 나쁜 코드가 되나요?
char* test[4] ; 을 받으려면 char*** test2로 해야하는 것같은데... 한차원씩 증가해서 넘겨야하는것같은데...
뭐랄까 아직도 잘 모르겠어요. 뭔가 이해하려다가 중간에 붕~ 뜬 기분입니다.
보충 설명 ㅜㅜ 좀;;;
아차, 코드 잘 보았고 많이 도움 됐습니다. 고마웠습니다. 부럽네요. ㅜ.ㅜ
포인터를 잘못
포인터를 잘못 사용한 게 한 두가지가 아니네요 -_-; 대충 아래와 같이 수정하면 문제는 없을겁니다.
char ** haha( ) // 오류 시 NULL 을 반환 하면 됩니다.
{
char **test2 = (char **) malloc( sizeof(char *) * 3 ); // char * 를 저장하는 주소니 char **
test2[0] = (char *) malloc( sizeof(char) * 5 ) ;
test2[1] = (char *) malloc( sizeof(char) * 5 ) ;
test2[2] = (char *) malloc( sizeof(char) * 5 ) ; // 3개 까지만 추가 할당
// 위 경우를 아래와 같이 한번에 할당 받으셔도 동일합니다.
// char **test2 = (char **) malloc( size(char) * 5 * 3 );
memcpy( &test2[0] , "AAAA" , 5 ) ; // memcpy( test2, "AAAA", 5) 와 동일합니다.
memcpy( &test2[1] , "BBBB" , 5 ) ; // memcpy( test2+5, "BBBB", 5) 와 동일합니다.
memcpy( &test2[2] , "CCCC" , 5 ) ; // memcpy( test2+10, "CCCC", 5) 와 동일합니다.
printf("<<< haha END >>>\n");
return test2; // 만들어진 char ** 주소 반환
}
int main(void)
{
int i=0;
char** a = haha();
for(i; i<3; i++ )
printf("%s\n", a[i] ) ;
// malloc 으로 각각 할당 받았기 때문에 해제도 해주셔야 합니다.
for(i=0; i<3; i++)
free(a[i]);
// 이것 역시 해제 해주셔야 합니다.
free(a);
return 0;
}
기존 코드 문제점 기술하면
1. haha 선언은 char * [] 형의 변수의 값을 참조만 하지 반환할 수 없는 형태 입니다.
** 형을 반환 받고자 한다면 *** 형으로 선언하고 내부에서는 해당 변수의 *argument 로 접근해야 합니다.
인자로 넘겨서 값을 넘겨 받고자 한다면 해당 변수의 주소를 넘겨야합니다.
그래서 주소값을 인자가 아니라 반환값을 사용하도록 함수형을 예에서는 일부 바꿨습니다.
2. malloc 할당 시 사이즈가 3개 이기때문에 [2] 까지만 할당 받아야 합니다.
정정..
익명으로 쓰니 수정을 못하니 불편하군요 ㅋㅋ
윗분도 답변 자세히 쓰셨는데 두가지 참조하시면 되겟네요.
동적으로 할당한
동적으로 할당한 메모리 인데. test2로부터 +,- 연산은 위험한 것이 아닌가요?
동적할당이라 여기저기 빈 메모리를 쓰는 것이 아닌가요?
혹시 순차적으로 malloc을 쓰지않고 다른 녀석과 함께 사용했으면 중간에 다른 변수가 차지하게 되는거 아닌가요?
위험 하지 않습니다.
위험 하지 않습니다. C 언어자체가 그렇습니다. 하나의 malloc 호출은 연속된 공간을 할당해 줍니다.
malloc 과 같은 최 하위 api 가 아닌 메모리를 할당받아 관리하는 클래스등이 구현 스펙에 따라 연속적인 공간을 할당받을지 구현 스펙에 제한적인것이지 malloc은 연속 공간을 할당 받습니다.
c의 array 접근 방식도 위와 같습니다. array 이기 때문에 그러합니다.
단, 특별한 경우가 아니면 array에 대해서 +, - 연산을 하지 않는것이 좋겠지요.
아아, 주석
아아, 주석 감사합니다. 뭔가 와 닿는 듯합니다. malloc쪽은 별표가 많아서 어려워보여요.
역시 더 공부가 필요하겠지요. 감사해요.
짧은 생각이지만...
malloc 함수를 지역함수에서 사용한다고 해서 메모리에서 값이 없어지는게 아니고..
지역함수 안에서 메모리 값이 없어지는게 아니라 그 메모리를 잡고 있는 포인터가 스택에서 사라지는 것으로
알고 있습니다.
고로 char *a에서 haha(a); 로 넘겨 준 것과 같이 인자값으로 넘겨준 포인터를 가지고 할당된 공간에 접근 할 수
있을것 같습니다~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
꽤나 솔직해 질 수 있다...
우연을 바라지 않는다면....
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
꽤나 솔직해 질 수 있다...
우연을 바라지 않는다면....
정보 고맙습니다.
정보 고맙습니다. 말씀대로 살아있네요.
그 함수가 종료되면
그 함수가 종료되면 할당된 주소를 접근할 수 없습니다.
포인터가 모두 레퍼런스가 되는게 아니라 포인터 자체가 값에의한 참조가 됩니다.
포인터가 참조가 되기위해서는 해당 변수의 주소가 인자로 넘겨져야합니다.
char * 를 전달만 하는게 아니라 다시 반환 받고자 한다면 char ** 여야 합니다.
char * 내에 저장된 char 값만 참조하고 바꾸고자 한다면 char * 만 인자로 넘겨도 됩니다.
인자가 반환될 경우는 위와 같이 해야하지만,
함수자체 반환값으 경우는 그 자체가 반환 값이기 때문에 char *를 반환 받고자 할때
char *를 반환 하면 되는 것이지요.
포인터라는 개념을 확실히 잡아야합니다.
포인터, 레퍼런스, 변수 라는 단어자체에 현혹 되지 말고 그 단어의 의미를 파악하고 계셔야합니다.
lvalue, rvalue 와 같은 용어도 그렇구요.
말씀 고맙습니다.
말씀 고맙습니다.
이부분이 중요한 말 같은데, 말이 좀 어렵군요;;;
어떤걸 말씀하시려는지 어렴풋이 감은 오는데, 아직;;; ^^;;
쉽다고 주장하고 싶은 설명
함수를 쓸 때 세 가지 정도의 유형이 있다고 하면,
정도가 있겠지요.
f1은 arg1의 값을 받기만 하고 고치지 않으므로 원형이 f1(type)이 됩니다.
f2는 arg2의 값을 받아서 처리 결과를 되돌리지만
고치지는 않으므로 원형이 type f2(type)이 됩니다.
그러나 f3은 arg3의 값을 받아서 고칠 수도 있어야 하므로
원형이 f3(type*)이 됩니다.
쉽게 설명해보려고 애 썼는데 쉬운지 잘 모르겠네요.
아흑! T_T
댓글 달기