Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

bool형의 배열을 리턴하는 함수

243 views
Skip to first unread message

kimj...@googlemail.com

unread,
Sep 27, 2006, 4:47:42 PM9/27/06
to
다음의 함수는 옳바른가요?

bool* getBoolArr()
{
bool bTemp[5];
.
.
.
return bTemp;
}

위의 코드를 넣어 컴파일 했더니

warning: address of local variable bTemp returned 라는 경고가
뜨고 컴파일은 제대로 되더군요.

리턴 받으려는 값은 물론 임의의 갯수(예제에서는
5개)만큼의 bool형 배열입니다.

올바른 방법을 가르쳐 주시면 감사하겠습니다.

Ji Hun SEO

unread,
Sep 27, 2006, 8:35:44 PM9/27/06
to
dar...@naver.com 쓴 글:

bTemp의 scope는 getBoolArr() 함수 까지 입니다.
이걸 벗어나면 그 메모리 영역은 해제가 됩니다.
그러므로 전역 변수(지양해야할 방법)를 사용하거나 argument로 배열을 받아
서 그 곳에 값을 저장하고 리턴 해주어야 합니다.
보통의 string 계열 함수가 argument와 리턴값이 같은 경우와 이와 같은 경우
입니다.
이의 구현을 위한 다른 여러가지 방법론이 있겠으나 이 방법이 가장 보편적입
니다.

<어떠한 역경에도 굴하지 않는 '하양 지훈'>

kimj...@googlemail.com

unread,
Sep 28, 2006, 3:40:23 AM9/28/06
to

답변 감사드립니다.

다만, 위의 함수에서 필요한 것은 변수 자체가 아니라
함수에서 처리된 값입니다.

제가 배열을 통째로 리턴할 수 있는 여러가지
스크립트 언어에 익숙해져 있어서 C에서도 자꾸
배열을 통째로 리턴하려는 시도를 하게 되는데 그게
가능한지, 가능하다면 어떤 식으로 구현해야
하는지가 알고 싶습니다.

비교를 하자면 char* somefunc(); 는 제대로 된
문자열(char형 배열)을 리턴하지 않습니까?

마찬가지로 bool* somefunc();나 int* somefunc();도 각 타입별
배열을 리턴해 주지 않을지 궁금합니다.

제가 C코드를 작성하는제 손이 익지 않아서 간단한
코드를 작성해서 가르쳐 주시면 정말 감사
드리겠습니다.

youngduk

unread,
Sep 29, 2006, 5:04:34 AM9/29/06
to
함수 내부에서 선언한 stack변수는 함수가 끝남과
동시에 사라집니다.
이것을 함수가 끝난 뒤에도 남아 있게 하려면
1. malloc을 이용하여 메모리 할당을 시켜서 넘겨준다.
2. 변수를 static으로 선언한다.
예 1)
bool *getbool()
{
bool *ret = (bool*)malloc(sizeof(bool)*5);
....
return ret;
}

예2)
bool *getBool()
{
static bool ret[5];
...
return ret;
}

그리고, 예를 드신 char *를 넘겨주는 것 역시 위 예
1혹은 2의 방식으로 구성되어 있을 것입니다.

darcy

unread,
Sep 29, 2006, 7:20:56 AM9/29/06
to

네, 무슨 말씀인지 이해가 되었습니다.

1처럼 메모리를 할당해서 리턴할 경우 메모리를
반환(free)할 시점을 자주 잊어 버리게 되서 걱정이
되네요. 결국은 주소에 의한 참조 이외의 마땅한 답은
없는 것이군요.

답변 감사드립니다.

김승범

unread,
Sep 29, 2006, 12:40:56 PM9/29/06
to
Ji Hun SEO wrote:
> 그러므로 전역 변수(지양해야할 방법)를 사용하거나 argument로 배열을 받아
> 서 그 곳에 값을 저장하고 리턴 해주어야 합니다.
> 보통의 string 계열 함수가 argument와 리턴값이 같은 경우와 이와 같은 경우
> 입니다.
> 이의 구현을 위한 다른 여러가지 방법론이 있겠으나 이 방법이 가장 보편적입
> 니다.

네, 말씀하신 것처럼, 호출하는 쪽에서 인자로 배열을 전달하도록 하는 것이
가장 활용성이 좋고 또 일반적입니다. 그러면 호출하는 쪽에서는 동적 할당을
받은 장소든지, 그 함수 안에서 선언한 자동 변수든지, 아니면 정적 변수든지
원하는 곳 어디에도 결과를 전해받을 수 있습니다. 멀티스레드 환경에서도
문제 없이 쓸 수 있고요.

이와 더불어, 돌려줄 내용의 길이가 정해져 있지 않은 경우 배열의 크기를
함께 전달해서 최대한 그만큼까지만 기록하도록 하는 패턴도 흔히 쓰입니다.
예컨대 fgets(line, sizeof line, file) 식으로 말이죠.

--
김승범

김승범

unread,
Sep 29, 2006, 5:51:17 PM9/29/06
to
youngduk wrote:
> 함수 내부에서 선언한 stack변수는 함수가 끝남과
> 동시에 사라집니다.
> 이것을 함수가 끝난 뒤에도 남아 있게 하려면
> 1. malloc을 이용하여 메모리 할당을 시켜서 넘겨준다.

이 방법은 메모리 누수를 일으키기 쉽다는 점과 속도가 느리다는 점
때문에 그리 바람직하지 않아 보입니다. 이러한 점에도 불구하고
동적 할당이 꼭 필요한 경우가 있고, 그런 경우에는 사용해야겠지만,
이 경우는 다른 좋은 방법이 있으니까요.

> 2. 변수를 static으로 선언한다.

이 방법은 함수를 호출할 때마다 결국 같은 배열을 내용만 바꾸면서
같은 주소를 돌려주는 것이기 때문에, 나중의 호출로 인해 이전 호출의
결과가 영향을 받게 됩니다. 예를 들어

bool* a = get_bool(...);
bool* b = get_bool(...);
if (a[0] && b[0]) { ... }

이러한 코드에서, 의도한 바는 처음의 호출이 돌려준 배열의 0번 요소와
나중의 호출이 돌려준 배열의 0번 요소를 검사하는 것이었지만, 나중의
호출에 의해 처음 호출의 결과는 덮어쓰이게 되므로 의도한 바를 얻지
못합니다. 즉 이 경우 이전 호출의 결과값을 보존하려면 따로 복사를 해
두어야 합니다.

또한 멀티스레드 프로그램에서도 문제가 됩니다. 스레드 A에서 함수를
호출하고 결과값을 읽기 전에 스레드 B에서 같은 함수를 호출하면, 스레드
A의 호출에서 저장된 값이 덮어쓰여서 스레드 A에서는 올바른 값을 얻지
못하게 됩니다.

이러한 문제를 갖는 표준 함수의 대표적인 예가 localtime인데, 이러한
문제를 해결하기 위해서 localtime_r, localtime_s 등의 "thread-safe"한
함수들이 제공되기도 합니다.

위에서 제시된 문제점 때문에, 배열을 돌려줄 때는 호출한 쪽에서 준비한
배열에 값을 채워주는 것이 가장 바람직하고 또 일반적입니다.

--
김승범

김승범

unread,
Sep 29, 2006, 6:02:27 PM9/29/06
to
dar...@naver.com wrote:
>
> 제가 배열을 통째로 리턴할 수 있는 여러가지
> 스크립트 언어에 익숙해져 있어서 C에서도 자꾸
> 배열을 통째로 리턴하려는 시도를 하게 되는데 그게
> 가능한지, 가능하다면 어떤 식으로 구현해야
> 하는지가 알고 싶습니다.

굳이 배열 자체를 통째로 돌려주어야 한다면,
구조체로 감싸서 돌려줄 수는 있습니다.

typedef struct { bool values[5]; } bool5;

bool5 get_bool5()
{
bool5 ret;
// ...
return ret;
}

bool5 ret = get_bool5();

그러나, 일반적으로 배열은 복사하는 데에 시간이 많이 걸리기 때문에
배열을 구조체에 넣어서 이렇게 돌려주는 것이 바람직하지는 않습니다.

> 비교를 하자면 char* somefunc(); 는 제대로 된
> 문자열(char형 배열)을 리턴하지 않습니까?

위 함수가 돌려주는 것 역시 하나의 주소일 뿐입니다. strcpy()처럼 호출한
쪽에서 준비된 주소를 그대로 돌려주는 경우도 있고, 함수 내부에 선언된
정적 배열이나, 동적 할당된 배열의 주소를 돌려주는 경우도 있습니다.

> 마찬가지로 bool* somefunc();나 int* somefunc();도 각 타입별
> 배열을 리턴해 주지 않을지 궁금합니다.

마찬가지로 이들이 돌려주는 것도 배열이 아니라 하나의 값을 가리키는
주소이거나 혹은 배열의 첫번째 요소를 가리키는 주소일 뿐입니다.
(보통 하나의 값은 그냥 값 자체를 돌려주면 되지 굳이 주소를 돌려줄
필요가 없기 때문에, 포인터를 돌려줄 경우 배열의 첫번째 요소를
가리키는 주소일 경우가 많습니다만.) 그 배열이 차지하는 공간이
어떻게 마련되는지는 경우마다 다르겠습니다.

> 제가 C코드를 작성하는제 손이 익지 않아서 간단한
> 코드를 작성해서 가르쳐 주시면 정말 감사
> 드리겠습니다.

여러 번 글을 올린 것처럼, 호출한 쪽에서 마련한 배열을 인자로
받아들이도록 하면 됩니다.

bool* get_bool(bool ret[5]) // (bool* ret)와 같은 의미
{
// ret[i] = ...
return ret;
}

bool ret[5];
get_bool(ret);

--
김승범

liebeym

unread,
Sep 30, 2006, 9:21:09 AM9/30/06
to
dar...@naver.com 쓴 글:

지훈님 말씀처럼 하셔도 되고 보통 malloc으로 메모리 할당을 해서 사용합니다.
그리고 반드시 free()시켜주시고요.

0 new messages