return하도록 하는 함수

ShaYEL의 이미지

C에서 함수가 return되도록 하는 함수를 짤 수 있나요?
이를테면,

function1(...)
{
	A를 만족하면 return하라.;
}
 
function2(...)
{
	.
	.
	function1(...);
	.
	.
}
 
main()
{
	.
	.
	function2(...);
	.
	.
}

이런 코드에서, main에서 function2를 실행하던 도중 A라는 조건을 만족하면 function1에 의해 function2가 return되고, main에서 마저 다음 명령을 수행하도록 하는 것이죠

mirheekl의 이미지

일단 질문하신게.. function1에서 바로 main으로 리턴해버리는걸 말씀하시는거죠? (아니라면 부연설명을 좀더 부탁드립니다)

언어 설계적 관점으로 보면 컨트롤을 메인 함수로 넘기는것 자체야 어렵지 않겠지만, 리소스 반환 등의 문제가 생길 수 있기 때문에 일부러 그런 구문을 넣지 않는걸로 보입니다. 저 경우에도 function2에서 선언한 리소스들은 반환 기회를 잡지 못한채 모두 날아가겠죠.. 자동변수야 회수가 가능하겠지만 동적으로 할당한건 반환할 기회가 없습니다. 결국 function2에서 function1의 리턴 코드를 보고 나서 필요한 자원을 반납 후 다시 main으로 리턴하는게 맞는 순서가 되는 것이죠.

사실 function1 자체를 아예 매크로로 구현해버리면 되긴 합니다. 허나 이래도 자원 반납의 문제는 고스란히 남겠죠. function2에서 사용하는 모든 리소스를 자동반납되는 형태로만 사용하거나, 아니면 function1 매크로 자체를 function2에 종속적으로 만들어 할당받은 자원까지 반납하게 만들어버리면 상관없겠지만요. 이런 건 실제로 가끔 보입니다만 매크로에서 분기를 하게 되면 가독성을 크게 해치므로 (예: 리턴 구문이 아무리 봐도 없는데 왜 특정 코드가 실행이 안되지????? 나중에 알고보면 일반 펑션 콜처럼 보였던 것중 하나가 매크로-_-) 개인적으로 선호하지 않는 방식입니다.

C++은 조금 더 사정이 나은 것이, 자원 반납 처리를 상당부분 자동화할 수 있고, 예외 처리가 가능하기 때문입니다. 예외를 이용하시면 원하시는 것과 거의 유사한 내용의 구현이 가능할듯 합니다. 사실 C에서도 예외처리 사용이 가능하니까 굳이 필요하시면 그쪽을 알아보시면 좋겠네요. 그렇다고 해도 function2나 메인 함수를 변경해야 함은 동일하겠죠. function1이 예외를 던지면 누군가 그걸 받아줘야 하고, function2에서 할당받은 리소스를 반납할 기회도 확보해야 하니까요.

--

chanik의 이미지

int function1(...)
{
	//A를 만족하면 return하라.;
	if(A) return 1;
	else  return 0;
}
 
function2(...)
{
	.
	.
	if(function1(...)) return;
	.
	.
}
 
main()
{
	.
	.
	function2(...);
	.
	.
}

"function1에 의해 function2가 return" 된다는 말에 부합되는지는 모르겠지만,
위와 같이 평범하게 작성하시면 function1()이 조건A 판별을 해주고 그 결과에 따라 function2()도 덩달아 리턴될 것입니다.
main()도 자연스럽게 다음 명령을 수행하게 될 것이고요.

--------

좀 다른 방법으로, 함수 경계선을 초월하여 goto 비슷하게 실행위치를 변경하려면
setjmp()/longjmp()를 이용할 수도 있습니다.
- http://www.jiniya.net/wp/archives/5030
- http://en.wikipedia.org/wiki/Setjmp.h#Simple_example

코드는 대략 아래와 같은 형태가 될 것입니다.

static jmp_buf buf;
int function1(...)
{
	//A를 만족하면 setjmp() 위치로 goto하라.;
	if(A) longjmp(buf);
}
 
function2(...)
{
	.
	.
	function1(...);
	.
	.
}
 
main()
{
	.
	.
	if (!setjmp(buf))  // 첫 실행시는 0 리턴. longjmp()로 되돌아왔을때는 1 리턴.
		function2(...);
	.
	.
}

function1()은 조건A가 확인되면 function2()를 무시하고 곧바로 최초의 setjmp(buf) 위치로 goto 합니다.
function2()가 점유하고 있던 로컬변수 등의 스택 내용물도 모두 무시되고
스택은 setjmp(buf) 호출되던 시점으로 되돌아갑니다. 그런 작업을 위해 jmp_buf가 필요했던 것이고요.

function2()가 벌여놓았던 일(열린 파일, 힙에 malloc()하고 free()하지 않은 메모리 등..)의 뒤처리도
자연스레 생략되니까 코드 작성시 유의해야 합니다.

이런 방법을 써 보시라는 뜻은 아니고 이런 것도 있다는 것만 알리고 싶었습니다.
매뉴얼에도 setjmp()/longjmp()는 프로그램을 난해하게 만드니 대안이 없는 경우에만 쓰라는군요.
http://man7.org/linux/man-pages/man3/setjmp.3.html

Quote:
setjmp() and sigsetjmp() make programs hard to understand and maintain.
If possible an alternative should be used.
익명 사용자의 이미지

오.. 생각보다 엄청 쉬운 방법이 있었네요 ;;

댓글 달기

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