휘샤's Blog
천천히 서둘러라


그나저나 이번에 학교에서 조그마한 c강의를 하게 되면서 들었던 의문
도대체 Call by Reference(이하 CBR)과 Call by Value(이하 CBV)를 나누는 이유는 뭘까?

예전에 지식인에 올라왔던 글



다름이 아니라 쪽팔리지만 이렇게 올립니다 분명히 에러도 안나는데

결과값이 안되네요

// test.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다.
//
#include
#include // malloc 함수 사용
typedef struct node_type{
int value;
struct node_type *link;
}NODE;
//함수 원형 선언
NODE* addNode(NODE *head_ptr); // 노드의 추가
NODE* deleteNode(NODE *head_ptr); // 노드의 삭제
void displayList(NODE *head_ptr); // 리스트 출력
void main(){
//변수 선언
NODE *head_ptr = NULL; // 노드 헤더 포인터
int select; // 작업 선택
//1. 원하는 작업 선택
printf("원하는 작업을 선택 하세요 ");
printf("(1:노드 추가, 2:노드 삭제, 3:리스트 출력, 4:작업 종료) ");
printf("Select : ");
scanf("%d",&select);
fflush(stdin);
while(select != 4){
switch(select){
case 1: //1.1 노드 추가
addNode(head_ptr); // 노드 추가 함수 호출(문제부분)
displayList(head_ptr);
break;
case 2: //1.2 노드 삭제
deleteNode(head_ptr); // 노드 삭제 함수 호출(문제부분)
displayList(head_ptr);
break;
case 3: //1.3 리스트 출력
displayList(head_ptr);
}
printf("원하는 작업을 선택하세요 ");
printf("(1:노드 추가, 2:노드 삭제, 3:리스트 출력, 4:작업 종료) ");
printf("Select : ");
scanf("%d",&select);
fflush(stdin); // 입력 버퍼 비우기
}//2. 작업 종료 선택 시까지 반복
}
/*********************************
노드의 추가
입력 : 노드의 해더 포인터 / 출력 : 추가 이후 노드의 해더 포인터
*********************************/
NODE* addNode(NODE *head_ptr){
//지역 변수 선언
NODE *pnode = (NODE *)malloc(sizeof(NODE)); // 동적 메모리 할당(문제부분)
//값 입력
printf("추가할 값 : ");
scanf("%d",&pnode->value); // pnode의 value값에 값 얻어옴(문제부분)
fflush(stdin);
// 추가
pnode->link = head_ptr;
head_ptr = pnode;
return head_ptr;
}
/*********************************
노드의 삭제
입력 : 노드의 해더 포인터 / 출력 : 추가 이후 노드의 해더 포인터
*********************************/
NODE* deleteNode(NODE *head_ptr){
int locate,i;
NODE* cursor = head_ptr;
NODE* temp;
printf("삭제할 위치 : ");
do{
scanf("%d",&locate);
if(locate <= 0){
printf("입력값은 0보다 큰 수입니다. ");
}
}while(locate <= 0);
fflush(stdin);

if(locate == 1){ // 처음 노드 삭제
head_ptr->link; //헤더의 링크 값을 헤더에 저장(문제부분)
free(cursor);
return head_ptr;
}
//2번째 이상 노드 삭제
for(i=1;i
if(cursor == NULL){
printf("삭제 대상 값이 없습니다. ");
return head_ptr;
}
cursor = cursor->link;
}
temp = cursor->link;
cursor->link = temp->link;
free(temp);
return head_ptr;
}
/*********************************
리스트 출력
입력 : 노드의 헤더 포인터
*********************************/
void displayList(NODE *head_ptr){
// list 출력
printf("Linked List :");
while(head_ptr != NULL){
printf("%5d",head_ptr->value);
head_ptr = head_ptr->link; //다음 링크로 이동(문제부분)
}
printf(" ");
}

책에 있떤 문제를 푸는건데 빈칸채워 넣기 인데 답이 안나오네요

옆에 문제부분이라는 곳이 원래 빈칸이였는데 제가 한건데 좀 안되네요..

좀 고수님들 부탁 드릴께요 ㅠㅠ 이상하게 노드 추가가 안된다는 쿨럭..

그럼 꼭 답변 부탁드립니다 그리고 답변 8일 오후 11시까지 받겠습니다


그리고 달았던 답변



포인터 등을 이용해 주소값을 넘겨줘서 다른 지역함수 내에서 값을 바꿀수 있게끔

하는 것을 Call by Reference (참조에 의한 호출)이라고 합니다. 그것을 이용해서 head_ptr이 가르키는 곳이 동적할당을 하는 부분을 가르키게 하는 것이 목적인 듯 싶은데요,





자세한 설명을 하자면,

변수는 만들어질때 (스택이든 힙이든) 어떤 메모리에 저장이 됩니다.

몇번째 주소에는 어떤 변수가 있다. 이런 내용으로요.



그런 개념으로 포인터를 하나의 변수로 보면 포인터도 메모리에 저장이 됩니다.

다만 그 메모리 안에 있는 내용이 다른 곳을 가르키는 주소가 저장된다는 것이

특징일 뿐이죠.



본론으로 들어가서

NODE* addNode(NODE *head_ptr){
//지역 변수 선언
NODE *pnode = (NODE *)malloc(sizeof(NODE)); // 동적 메모리 할당(문제부분)
//값 입력
printf("추가할 값 : ");
scanf("%d",&pnode->value); // pnode의 value값에 값 얻어옴(문제부분)
fflush(stdin);
// 추가
pnode->link = head_ptr;
head_ptr = pnode;
return head_ptr;
}
라는 함수가 있습니다.



main함수에서 이 내용을 호출할때

addNode(head_ptr); // 노드 추가 함수 호출(문제부분)

이런 식으로 head_ptr이 가르키고 있는 주소값을 넘겨주는데요.



이 주소값을 넘겨받을 때 지역 함수에서 매개 변수로 받는 (NODE *head_ptr) 부분에서

(NODE *)라는 타입의 변수를 또 하나 만들어서 거기에다 main에서 넘겨준 주소값을

입력하게 됩니다.



요약하자면, 새로 포인터를 만들어서 그곳에 주소값을 넘겨받았는데,

그 포인터가 가르키는 주소값이 바뀐다고 해도 main에 있는 포인터가 가르키는

주소값은 변함이 없다는 말입니다.


참 지금 생각해봐도 교과서적인 답변이었던것 같다,
프로그래밍을 배운지 1년도 안된 인간이 더 쉽게 답변할수 있을리가 없지 않는가;
지금 생각해보면 지금 실력보다 저 답변을 달았던 때의 실력이 좀 더 나았던거 같다,
아무래도 휴식기...라기보다 공부 안하고 농땡이 피웠던 기간이 너무 길었다;;


아무튼, 본론으로 들어가보자.
CBR이 CBV와 다르다고 지적되는 이유가 다른 함수에서 선언된 변수의 내용을 바꿀수 있어서라고 한다.
글쎄, 하지만 그건 함수의 인자(argument)에 따른 기능이 아닐까,
저런 식으로 따지면 Call By Int value, Call By Char Value, 라는 것도 있어야 하지 않을까 라는 생각을 한다.

저기 있는 답변에서 "새로 포인터를 만들어서 그곳에 주소값을 넘겨받았는데"라는 부분.
그렇다, 어차피 인자로 받는 내용은 또다른 함수에서 선언되어 내용이 복사되는 것과 같지 않는가?
예를 들어,
void f(int a)
{
}

int main(void)
{
        int a;
        f(a);
}



라는 소스에서 main함수에서 선언된 a는 f라는 함수로 보내질때
f라는 함수에 또다시 int a를 선언한 후 main 함수에 있는 내용을 a에 복사한다는 것이다.

실제로 중간에 printf를 써서 주소를 출력해보면,
address of a is [bffffa54] "in main"
address of a is [bffffa40] "in f"
이렇게 다른 주소값이 출력이 된다.
이정도는 다들 알고 있으리라 생각하고 넘어가겠다

그렇다면 CBR에서는?
우선 아래 소스를 보자.

void f(int a)
{
        a=1;
        printf("value of a is [%x] "in f" ", a);
}

int main(void)
{
        int a=5;

        printf("value of a is [%x] "in main" ", a);
        f(a);
}
이 소스에서 출력되는 것은 예상이 될 것이다.
그렇다면
void f(int *p)
{
        *p=1;
        printf("value of a is [%x] "in f" ", *p);
}

int main(void)
{
        int a=5;
        int *p=&a
        printf("value of a is [%x] "in main" ", a);
        f(p);
}
이 소스 역시 어떻게 출력될 것인지 예상 될 것이다.
이것이 흔히들 말하는 CBV와 CBR의 차이일 것이다.




그렇다면 다음 소스를 살펴보자
#include <stdio.h>

void f(int *p)
{
        printf("address of p is [%x] "in f" ", &p);
}

int main(void)
{
        int *p, a;
        p = &a;

        printf("address of p is [%x] "in main" ", &p);
        f(p);
}
이 소스에서 어떻게 출력될 것 같은가?
눈치 빠른 사람, 혹은 이미 알고 있는 사람은 알겟지만
address of p is [bffffa54] "in main"
address of p is [bffffa40] "in f"
라고 출력이 된다.
이것은 포인터 역시 새로 선언되어 주소값이 복사되어 온다는 것을 뜻한다.
int 역시 그 값이 복사되는 것이고, 포인터 역시 그 값이 복사되는 것이면 그 차이가 뭘까?



하고 싶은 말을 요약하자면,
어차피 다른 함수로 보낼때 새로운 변수가 선언되고 그 값만 복사된다는 것인데,
왜 CBV와 CBR의 구분을 두는가에 대한 의문이다.

int를 인자로 넘기면 정수를, char를 인자로 넘기면 문자형을, 포인터를 인자로 넘기면 주소값이 넘어가는 것,
즉 안에 있는 값을 복사해 준다는 것은 똑같은데 왜 다르게 표현하는 것일까,

Creative Commons License
Creative Commons License
1  ... 20 21 22 23 24 25 26 27 28  ... 31 
분류 전체보기 (31)
FreeTalk (16)
Review (3)
Wish (3)
Tip (6)
1. 2. 3. href="http://cfs.tistory.com/custom/blog/0/2428/skin/images/SyntaxHighlighter.css">
4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 22.