2013-01-04 2 views
3

내 C 라이브러리에서 작업하는 C 기술을 제거하고 있습니다. 처음으로 작업을 구현 한 후에는 코드를보다 효율적으로 만들려고합니다. 현재 함수 매개 변수를 참조 또는 값으로 전달하는 주제가 있습니다.C에서 함수 매개 변수를 값으로 전달하는 이유는 무엇입니까?

제 질문은 왜 C로 값으로 함수 매개 변수를 전달할 수 있습니까? 코드가 더 깨끗해 보일 수도 있지만 참조로 전달하는 것보다 항상 효율적이지는 않습니까?

+11

** 모든 ** 인수는 C에서 값으로 전달됩니다. 포인터보다 크지 않으면 복사본을 전달하는 것이 덜 효율적이지는 않습니다. –

+0

불편한 점은 말할 것도 없습니다 :'int get_int(); void process_int_A (const int x); void process_int_B (const int * const x);'. 비교 :'void foo() {process_int_A (get_int()); }'vs'void foo() {const int result = get_int(); process_int_A (& result); }'. 모든 반환 값에 대해 명시적인 중간 저장 공간이 필요하면 킬러가됩니다. C++에서 임시 값에 바인딩 할 수있는 "실제"참조가있는 문제는 적습니다. – GManNickG

답변

5

C에서 모든 인수는 값으로 전달됩니다. 당신이 전혀 명시 적 간접없이 변경의 효과를 볼 때 참조로 진정한 패스는 다음과 같습니다

int sum(int a, int b) { 
    return a + b; 
} 

당신은 쓸 것이다 :

void f(int c, int *p) { 
    c++; // in C you can't change the original paramenter passed like this 
    p++; // or this 
} 

하지만 대신 포인터의 값을 사용하여 자주 바람직하다 예 :

int sum(int *a, int *b) { 
    return *a + *b; 
} 

안전하지 않으며 비효율적이기 때문에. 추가적인 간접 지정이 있기 때문에 비효율적입니다. 또한 C에서 포인터 인수는 포인터를 통해 값이 수정된다는 것을 호출자에게 알립니다 (특히 뾰족한 유형의 크기가 포인터 자체보다 작거나 같은 경우).

+0

이것은 어리석은 질문 일 수 있지만, 왜''int sum (int * a, int * b) {return * a + * b; }'''함수가 안전하지 않습니까? – c00kiemonster

+0

포인터를 사용하지 않고 절대로 NULL/dangling 포인터를 간접적으로 사용할 위험이 있기 때문입니다. – perreal

+3

발신자는 이제 a 및 b에 대한 변수를 만들어야하며 상수는 전달할 수 없습니다. 호출자는 값을 'malloc'할 필요가 있는지 또는 변수의 주소를 전달해야하는지 결정해야하며, 변수가 'const'가 아니기 때문에 (값을 복사 할 필요가있을 수 있음) 값을 수정할 수 있다고 가정해야합니다. 역 참조 포인터는 호출자가 'NULL', 초기화되지 않은 포인터 및/또는 잘못된 메모리 위치에 대한 포인터를 전달하는 경우 안전하지 않습니다. – Joe

1

Passing by reference in C을 참조하십시오. 참조에 의한 전달은 C에서 잘못된 이름입니다. 변수 대신 변수의 주소를 전달하는 것을 말하지만 변수 에 대한 포인터를 값으로 전달하고 있습니다.

즉, 변수를 포인터로 전달하면 예가 더 효율적이지만 주된 이유는 포인터가 가리키는 원래 변수를 수정할 수 있기 때문입니다. 이 작업을 수행하고 싶지 않은 경우 의도를 명확히하기 위해 값으로 가져 오는 것이 좋습니다.

물론이 모든 것은 Cs 무거운 데이터 구조 중 하나의 관점에서는 의미가 없습니다. 배열은 포인터에 의해 첫 번째 변수에 전달됩니다.

+3

** ** ** ** 정보 **에 대한 ** ** 감사합니다. – Joe

0

두 가지 이유 :

  1. 종종 당신이 많은 시간에 통과 한 포인터 역 참조 (대한 루프 긴 생각)해야합니다. 해당 주소의 값을 조회하고 싶을 때마다 역 참조를 원하지는 않습니다. 직접 액세스가 빠릅니다.

  2. 때로는 함수 내에서 전달 된 값을 수정하려고하지만 호출자에서는 수정하지 않으려합니다. 예 : 당신이 참조에 의해 전달 뭔가 위를하고 싶었다 경우

    void foo(int count){ 
        while (count>0){ 
         printf("%d\n",count); 
         count--; 
        } 
    } 
    

, 당신은 먼저 저장하는 함수 내부에 또 다른 변수를 만들 수 haev 것이다.

+0

변수에 대한 직접 참조를 역 참조하는 성능상의 불이익은 무엇입니까? 그것은 크기가 큰 토지에 있습니까? – c00kiemonster

+0

3 사이클 대 1 사이클이 될 수 있습니다. 쿼드 코어 머신을 프로그래밍하는 경우 누가 (주로) 신경을 씁니까? 성능 기반 (실시간 애플리케이션, 임베디드 시스템)을 구축하는 경우 큰 차이가 발생할 수 있습니다. – Phonon

+0

프로필, 프로필, 프로필! 이 답변의 1 부는 매우 추측적이고 컴파일러 최적화를 고려하지 않습니다. – Dan

5

컴퓨터를 코드하는 것이 다음 사람의 코드 작성만큼 중요하지 않기 때문에. 참조를 전달하는 경우 모든 독자는 호출 된 함수가 매개 변수의 값을 변경할 수 있다고 가정해야하며 호출하기 전에 매개 변수를 검사하거나 매개 변수를 복사해야합니다.

함수 서명은 계약이며 코드를 위로 나눕니다. 따라서 코드 기반을 작성하는 참조를 전달하여 일부 영역에서 무슨 일이 벌어지고 있는지 파악할 수 있습니다. 다음 사람의 삶은 더 나빠질 것입니다. 프로그래머로서의 가장 큰 일은 다음 사람의 삶을 더 좋게 만들어야한다는 것입니다. 왜냐하면 다음 사람이 아마 당신이기 때문입니다.

+1

좋은 답변입니다. 또한 (다른 것들 중에서) 컴파일러는 인수가 서로 별칭이 아니므로 더 나은 코드를 생성 할 수 있으므로 값 전달은 실제로 더 빠를 수 있습니다. – Nemo

+0

"다음 사람의 삶을 악화시키는"예는 좋은 것입니다. 그것은 내가 간과 한 것입니다. – c00kiemonster

+0

그리고 나는 항상 다음 사람이 당신의 주소를 아는 살인 광인이라고 생각했습니다. –

관련 문제