초보적인 질문인데요....call by reference 방식좀 알려주세요~~

cromkhc의 이미지

#include<stdio.h>

void F_ref(int *X, int *Y, int *Z); // Function Prototype declare, by referece

// global var
void main()
{
int A = 22;
int B = 32;

int A2;
A2 = A+B;

F_ref(&A2, &A, &A); //여기서 value 방식으로하면
(A+B, A,A)인데요... ref방식으로 해야해서 주소를 넘거야 하는데 &A+&B로 해야하는데 에러가 나더라구요.. .그래서 변수를 하나 선언해서 보냈는데 괜찮은 방법인가요?

printf("A+B=%d, A=%d, A=%d\n", A2, A, A);
}

void F_ref(int *X, int *Y, int *Z) // 54 22 22
{
*Y = *Y + 1; // 22+1=23 //value & ref와 ref인경우만 리턴
*Z = *Z + *X; // 22+54=76 //value & ref와 ref인경우만 리턴
}

그리고 ref 방식이라 그런가... 리턴 되는 값이 제가 생각한거 하고는 다르게 넘어가던데.,..... 참 어렵습니다.
값이 54, 77, 77 로 찍혀요....
제가 생각했던 값하고는 거리가 좀 있어서리....
고수님들 알려주세요~~~

kslee80의 이미지

소스 코드를 올리실때는 BBcode 를 이용하시는게 보기에 좋습니다.

그리고 C 언어에서는 call by reference 방식의 함수 호출은 불가능합니다.
일부 책이나 문서에서는 현재 코드에 쓰신 것처럼 하는것이
call by reference 라고 하는 경우가 있는데 이는 잘못된 설명입니다.
C 언어는 단지 call by value 방식만을 사용 가능합니다.
글에 쓰여진 함수도 call by value 방식으로 호출됩니다.

(소스 코드를 보건데 C++ 은 아닌듯 싶어서 C 라고 가정했습니다)

Quote:
F_ref(&A2, &A, &A); //여기서 value 방식으로하면
(A+B, A,A)인데요... ref방식으로 해야해서 주소를 넘거야 하는데 &A+&B로 해야하는데 에러가 나더라구요.. .그래서 변수를 하나 선언해서 보냈는데 괜찮은 방법인가요?

다른 방법은 없습니다

void F_ref(int *X, int *Y, int *Z) // 54 22 22
{
*Y = *Y + 1; // 22+1=23 //value & ref와 ref인경우만 리턴
*Z = *Z + *X; // 22+54=76 //value & ref와 ref인경우만 리턴
}

Y 와 Z 는 같은 변수의 포인터이기 때문에,
*Y = *Y + 1; 이라는 코드가 수행된 이후 *Y 와 *Z 의 값은 똑같이 23이 됩니다.
따라서, *Z 의 값은 23 + 54 = 77 이 되죠
cromkhc의 이미지

아 그렇군요.... 저도 그래서 곰곰히 생각해 보니까
님이 말씀하신대로 나오더라구요...
그런데 C언에서 call by value방식만 있다는건...첨 들어보네요
여태까지 포인터를 써서 참조하는 걸 reference 방식이라고
배웠는데.....
암튼 고맙습니다. ^%^

익명 사용자의 이미지

공부를 더 하시면 지금 하는게
call by value 인지 call by reference 인지
이런거 따지지 않고
걍 자연스럽게 논리적으로 프로그래밍을 하게 됩니다.

현학적이라고 표현을 하던가요?
가끔 질문들을 보면
요새 좋은 책도 많긴 하지만,
초보자들이 쓸데없는것에 매달리게 해서
시간을 뺐기고 고민하게 만드는 책도 많은듯 싶습니다.

잘난척하는게 부끄러워서 손님으로 씁니다 ^^

cromkhc의 이미지

절대 그렇지 않습니다. 모든 답글에 귀기울이기 때문에 그런 걱정 안하셔도
됩니다. ^^
저도 예전에 공부할땐 기냥 이런거 안따지고 했는데
과목에 PL이 있어서 과제로 하고 있거든요.....
암튼 저도 전공을 한지는 오래됐지만, 다른 것을 공부중이라
이쪽에 관심을 못쏟고 있네요.....
아무튼 모든 답글들 감사 드립니다. ^^

doldori의 이미지

cromkhc wrote:
그런데 C언에서 call by value방식만 있다는건...첨 들어보네요
여태까지 포인터를 써서 참조하는 걸 reference 방식이라고
배웠는데.....

C에서의 함수 호출은 항상 call by value입니다. 포인터를 써서 call by reference의
효과를 낼 뿐입니다. 함수 인자로 쓰인 포인터 변수 자체가 복사되어 넘겨진다는 점을
생각해 보세요.
익명 사용자의 이미지

[queto]현학적이라고 표현을 하던가요?
가끔 질문들을 보면
요새 좋은 책도 많긴 하지만,
초보자들이 쓸데없는것에 매달리게 해서
시간을 뺐기고 고민하게 만드는 책도 많은듯 싶습니다. [/queto]
앞서 말씀하셨지만, 이들간의 구분이 별 필요없을듯 하군요.
애초에 call by reference 라는것이 없습니다.
지금과 같은 CPU 구조에서는요.
다만 call by value 를 call by reference 처럼 보이게 만든것이 reference 입니다..
엄격하게 call by reference와 call by value를 구분하려면...

void func(int value[3])
{
    value[0] = value[1] = value[2] = 0;
}

int value[3] = { 1, 1, 1 };
func(value);

후에 value[3] 의 값은 [1,1,1] 이어야만 합니다.
보기에 call by value 처럼 보이기 때문이죠.
보다 정확하게 call by reference를 정의하려면.
func의 type이 "void func(int& value[3])" 이 되어야겠죠.

PS:
로그인 하기가 귀찮군요...

익명사용자의 이미지

메인함수내에서 이렇게 선언하고
int value[3] = { 1, 1, 1 };

test(value); 이렇게 호출하여

void test(int d[3])
{
d[0] = d[1] = d[2] =0;
}
이런 함수를 호출했더니

메인에서 value의 값을 찍어본 결과 0, 0, 0이 나왔습니다.
1, 1, 1이 나와야하는거 아닌가요?

익명사용자의 이미지

위의 글을 올린 분과는 다른 사람입니다만... 글의 의도는 다른 것 같네요.
C언어에서 배열은 포인터와 거의 동급입니다. (몇몇 경우에는 다른 행동이 나타나기도 합니다만 대부분의 경우 치환해도 문제가 발생하지 않습니다.)
따라서 int d[]를 인자로 넣었다면 int *d와 같으므로 call by reference의 효과가 나타나는 것입니다. 인용하신 글에서는 call by value 처럼 선언했는데 실제로는 call by reference의 효과를 보이는 것에 대해 지적한 것으로 보입니다.

익명사용자의 이미지

레퍼런스를 실험해 보기 위해 아래와 같은 형태로 함수를 만들었는데
에러가 나네요..
C++에서 하신거 맞죠?

void func(int& value[3])
{
....
}

flyingykk의 이미지

궁금해서 그러는데요 바로 위의 글에 나온 코드에서

void func(int value[]) { ... }

또는

void func(int *value) { ... }

로 하지 않고
void func(int value[3]) { ... }
으로 한 것은 특별한 이유가 있나요?
zelon의 이미지

인자를 int 배열이 3개인것만 받으려는 의도가 아닐까요?

int value[] 나 int * 는 int 배열이 2개이거나 더 작을 수 있으니, value[2] 를 할 때 오류를 낼 수 있죠.

-----------------------------------------------------------------------
GPL 오픈소스 윈도우용 이미지 뷰어 ZViewer - http://zviewer.wimy.com
블로그 : http://blog.wimy.com

doldori의 이미지

zelon wrote:
인자를 int 배열이 3개인것만 받으려는 의도가 아닐까요?

그런 의도였다면 완전히 무의미한 시도입니다. 다음의 선언은 모두 "동일"합니다.
void func(int value[]) ;
void func(int* value);
void func(int value[3]);

zelon wrote:
int value[] 나 int * 는 int 배열이 2개이거나 더 작을 수 있으니, value[2] 를 할 때 오류를 낼 수 있죠.

그와 비슷한 용도로 쓰이는 것이 C99에 추가된 static입니다.
void func(int value[static 3]);

이것은 함수의 인자가 적어도 3개의 원소를 갖는 int 배열이어야 함을 뜻합니다.

ps. static만큼 다양한 용도로 쓰이는 키워드는 없을 것 같군요.

익명사용자의 이미지

확실히 static에는 의미가 너무 많이 들어가 있어서 개념에 혼란을 일으키기 쉬운 키워드인 것 같네요. 다음 표준(제정을 할 지는 모르겠지만)에서는 각 기능을 따로 분리해서 새로 키워드를 만드는게 차라리 깔끔하지 않을까 싶네요.

htna의 이미지

doldori wrote:
void func(int value[static 3]);

이것은 함수의 인자가 적어도 3개의 원소를 갖는 int 배열이어야 함을 뜻합니다.

ps. static만큼 다양한 용도로 쓰이는 키워드는 없을 것 같군요.


C++의 자잘한 문법이 짜증나게 하는 순간이군요...
잘하면 staci에 객체가 생성되지 않도록 막는 문법도 있지 않을까.. ^^;;
그럴일은 없겠죠. ?

WOW Wow!!!
Computer Science is no more about computers than astronomy is about telescopes.
-- E. W. Dijkstra

doldori의 이미지

htna wrote:
C++의 자잘한 문법이 짜증나게 하는 순간이군요...

저는 C++이 아니라 C 얘기를 한 건데요. -.-a
C++에는 이런 문법이 없습니다.
익명 사용자의 이미지

doldori wrote:
htna wrote:
C++의 자잘한 문법이 짜증나게 하는 순간이군요...

저는 C++이 아니라 C 얘기를 한 건데요. -.-a
C++에는 이런 문법이 없습니다.

하하 C99 군요..

PS:
근데 이거 글 올리는 창, 디폴트로 크게 하는 법 없나요 ???
매번 크기를 증가시키려니 짜증나서리..

nahanjang의 이미지

Quote:

그리고 C 언어에서는 call by reference 방식의 함수 호출은 불가능합니다.
일부 책이나 문서에서는 현재 코드에 쓰신 것처럼 하는것이
call by reference 라고 하는 경우가 있는데 이는 잘못된 설명입니다.
C 언어는 단지 call by value 방식만을 사용 가능합니다.
글에 쓰여진 함수도 call by value 방식으로 호출됩니다.

전 그냥 값으로 전달되는 경우를 - 호출측 변수(상수)를 피호출함수에서 변경할수 없을때 call by value 로 생각하고
주소값으로 전달되는 경우를 - 피호출함수(*,&로 호출시)에서 호출측의 변수의 값에 변경을 가할수 있을때를 call by reference 라고 개념을 잡았었는데...
이게 잘못된건가요??
nahanjang의 이미지

Quote:

그리고 C 언어에서는 call by reference 방식의 함수 호출은 불가능합니다.
일부 책이나 문서에서는 현재 코드에 쓰신 것처럼 하는것이
call by reference 라고 하는 경우가 있는데 이는 잘못된 설명입니다.
C 언어는 단지 call by value 방식만을 사용 가능합니다.
글에 쓰여진 함수도 call by value 방식으로 호출됩니다.

전 그냥 값으로 전달되는 경우를 - 호출측 변수(상수)를 피호출함수에서 변경할수 없을때 call by value 로 생각하고
주소값으로 전달되는 경우를 - 피호출함수(*,&로 호출시)에서 호출측의 변수의 값에 변경을 가할수 있을때를 call by reference 라고 개념을 잡았었는데...
이게 잘못된건가요??
sodomau의 이미지

nahanjang wrote:
Quote:

그리고 C 언어에서는 call by reference 방식의 함수 호출은 불가능합니다.
일부 책이나 문서에서는 현재 코드에 쓰신 것처럼 하는것이
call by reference 라고 하는 경우가 있는데 이는 잘못된 설명입니다.
C 언어는 단지 call by value 방식만을 사용 가능합니다.
글에 쓰여진 함수도 call by value 방식으로 호출됩니다.

전 그냥 값으로 전달되는 경우를 - 호출측 변수(상수)를 피호출함수에서 변경할수 없을때 call by value 로 생각하고
주소값으로 전달되는 경우를 - 피호출함수(*,&로 호출시)에서 호출측의 변수의 값에 변경을 가할수 있을때를 call by reference 라고 개념을 잡았었는데...
이게 잘못된건가요??

어떤 서브루틴이나 펑션의 인자에 대한 변경이 원래 변수의 값에 영향을 미칠때 call by reference라 합니다.
포인터를 이용하면 call by reference를 흉내낼수 있지만, call by reference는 아니죠.

익명사용자의 이미지

그럼 call by reference 를 지원하는 프로그래밍 언어는 무엇인가요?
혼란스럽네요.

doldori의 이미지

제가 아는 것으로는 C++과 FORTRAN이 있습니다.

magingax의 이미지

처음엔 신기하고 편리해 몇번 썻지만..프로젝트가 커지면 헷갈리고.
C 코드와 섞어 짤경우 더 헷갈리고.
DLL로 만들어 다른언어에서 콜할때는 처음부터 다시짜야할수도 있습니다.
그냥 포인터 쓰세요..깔끔하고 좋잖아요..

LISP 사용자모임
http://cafe.naver.com/lisper
방송기술 개발업체
http://playhouseinc.co.kr

doldori의 이미지

일리는 있는 말씀입니다만,

using std::string;
 
void f(const string* s);
 
void g(const string& s);
 
string temp;
f(&temp);
 
g("temporary object behind the scene");

f()의 경우 임시 개체를 함수 인자로 쓰려면 반드시 먼저 선언을 해야 하지요.
저는 이런 불편함은 못 참는 성격이라서... ^^;
그리고 연산자 오버로딩에서도 참조형을 쓰는 것이 훨씬 자연스럽고요.
ㅡ,.ㅡ;;의 이미지

f(char *s );
f("temporary object behind the scene");

마찬가지로 쓸수 있습니다.


----------------------------------------------------------------------------

강철의 코딩술사의 이미지

포인터를 이용하는 방식이고 밸류도, 레퍼런스도 아니라면

call by address라고 부르면 되지 않을까요?

옛날에 세가지 방식으로 배운 것 같지 말입니다.

ㅡ,.ㅡ;;의 이미지


말장난 같은데요..

자바나 다른언어가 나오기이전에 이미 C 에서는 값호출 참조호출 등으로 구분되었죠..
즉 call by value, call by reference ...

근데 왜 원개념을 뒤흔들죠?
오히려 개념을 잘못이해한건 C에 call by reference 가 없다고 한쪽아닌가요.

예를들어 현재의 자바나 기타언어에서 클레스기능에 약간의 기능을추가한후에...

자바에는 클레스가 없다 라고 주장한다면..? 현재까지 자바를 해온사람들은 매우황당하겠죠..


----------------------------------------------------------------------------

kslee80의 이미지

C 언어에서 포인터를 이용한 call by reference 흉내를 어째서 call by reference 와 같다고 생각하시는지 모르겠군요.
call by reference 를 지원하는 언어와, 지원하지 않는 언어에서 포인터를 이용해서 흉내낸 것은
함수 호출시에 stack 구성이 틀려지기 때문에 같다고 할 수 없습니다.

ㅡ,.ㅡ;;의 이미지

스텍 구성이 어떻게 틀린가요?

궁금한게 어떤 언어든 주소를 넘기지 않고 가능한가요?


----------------------------------------------------------------------------

IsExist의 이미지

언어적 관점에서 구분합니다.

call by value, call by reference, call by name

이 셋 다 스텍구성으로 구분하지는 않습니다.

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

kslee80의 이미지

언어적 관점에서 구분하는게 맞죠.
단지, 언어적으로만 그렇게 구분되지 실제로는 차이 없는게 아니냐...라는 분위기로 흐르는 듯 싶어서
글을 작성했습니다.

kslee80의 이미지

C 에서 포인터를 사용한 call-by-reference 흉내의 경우,
호출된 함수의 스택에 넘겨받은 주소를 보관하기 위한 로컬 변수가 생성됩니다. (이것은 call-by-value 와 다를 봐가 없죠)

하지만, call-by-reference 를 지원하는 언어의 경우,
스택에 넘겨받은 주소를 보관하지 않습니다.
(죄송합니다. 여기까지만 알고 있습니다. 실제로 어디에 보관하는지는 잘 모르겠네요 ;;;
해당 언어의 컴파일러의 구현에 따라서, call-by-value 처럼 스택에 가상 변수를 할당하고 주소를 보관할 수도 있겠습니다만,
그런식의 "멍청한" 구현을 하지는 않았을 것이라고 생각합니다.)

ㅡ,.ㅡ;;의 이미지

인용:(call-by-value 처럼 스택에 가상 변수를 할당하고 주소를 보관할 수도 있겠습니다만,
그런식의 "멍청한" 구현을 하지는 않았을 것이라고 생각합니다)

라고 하셨는데 그럼 주소를 보관하지 않고도 가능할수 있단말인가요?
그런방법 이 어떤방법인지 매우궁금합니다.


----------------------------------------------------------------------------

전웅의 이미지

aliasing 을 시키는 방법이 있습니다. 함수 인자-매개변수 관계에서는
dynamic binding 이 필수겠지만, 인터프리터 기반의 언어나 스크립트 언어
에서는 그리 비용이 크지 않습니다.

구현 관점에서 동일하기 때문에 보다 상위 계층인 언어 정의/기술 관점
에서의 구분이 모호하다/불필요하다는 논리는 (다소 극단적이긴 하지만)
결국 컴퓨터는 회로 위 전류의 흐름일 뿐이므로 CPU 내 논리 회로의 구분이
불필요하다는 논리와 다를 바 없습니다.

동일한 pseudo-code 를 놓고 각 호출 방식에 의해 서로 다른 결과가 나오는
경우를 본다면 (PL 시험 문제 단골 손님이죠) 언어 차원에서의 차이를 보다
분명히 확인할 수 있지 않을까 생각합니다.

--
Jun, Woong (woong at icu.ac.kr)
Web: http://www.woong.org (서버 공사중)

--
Jun, Woong (woong at gmail.com)
http://www.woong.org

익명사용자의 이미지

유감스럽게도 무식하다고 설명하신 그 방법(주소를 스택에 저장해서 인자로 전달하는 방법)이 현재의 C++ 컴파일러가 사용하고 있는 방법입니다. C++과 C는 실제 컴파일 된 이후의 기계어 코드에서 큰 차이를 보이지 않습니다. 스택의 생성 방법은 예전의 C언어의 Calling Convention을 그대로 물려 받았습니다. 레퍼런스의 구현은 예전의 포인터 구현과 다른 점이 없습니다. 즉, 생성된 코드의 근본은 안바뀌었다는 얘기입니다. 간략히 말하면 적어도 포인터(또는 레퍼런스)를 다루는 방법에 있어서 C++ 컴파일러와 C언어 컴파일러에서의 차이는 없습니다.

댓글 달기

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