2013-04-18 4 views
5

에서 함수에 구조체를 전달 -나는 다음과 같은 경우 C

struct foo 
{ 
    int a; 
    int *b; 
} bar; 

void baz(struct foo qux) 
{ 

} 

있습니까 권리 bar의 로컬 복사본에 barbaz()에 결과를 전달하는 스택으로 푸시되고 있다는 생각에 나는? 그렇다면 어떤 종류의 사본입니까? C++에서는 복사 생성자 또는 기본 복사 생성자를 호출한다고 가정하지만 C에서 이것이 어떻게 작동하는지 실제로 알지 못합니다.

C에 기본 복사 생성자의 개념이 있으며 이름? 깊은 사본을 수행하기 위해 뭔가를 할 수 있습니까? (가상으로). 내가 생각할 수있는 유일한 방법은 사실 깊은 복사를 한 다음 함수에 전달하는 것입니다.

일반적으로 나는 포인터를 foo에 전달할 것이지만 어떻게 작동하는지 궁금 할 것입니다. 또한 포인터를 전달하는 것이 더 빠르며 메모리를 절약하고 이런 종류의 작업을 수행 할 때 취할 수있는 권장 조치라고 생각합니다. 나는 그것이 얕은 복사라고 생각할 것이다. 이것이 바뀔 수 있습니까?

답변

4

bar bar (bar)를 통과하면 막대의 로컬 복사본이 스택에 푸시됩니다.

예.

난 정말이가 C++의 기본 복사 생성자와 마찬가지로

실질적으로 C에서 어떻게 작동하는지 모른다; 사본의 모든 필드는 원본의 해당 필드로 초기화됩니다. 물론, "마치 같은"규칙 때문에 전체가 memcpy으로 종결 될 수 있습니다.

포인터를 전달하는 것이 더 빠르며 메모리가 절약된다는 느낌을 받고 있으며 이러한 종류의 작업을 수행 할 때 권장되는 조치 과정입니다.

대용량의 경우 struct 일 경우가 많지만 항상 그런 것은 아닙니다. 작은 필드 수가 적은 struct이 있으면 복사의 오버 헤드가 간접 참조보다 작을 수 있습니다 (C 및 C++의 앨리어싱 규칙으로 인해 일부 최적화가 수행되지 않을 수 있으므로 포인터 매개 변수를 사용하면 값이 비쌀 수 있습니다).

나는 그것이 얕은 복사라고 생각합니다. 이것이 바뀔 수 있습니까?

아니요, 얕은 복사본 (각 필드를 맹목적으로 복사)은 기본 복사 생성자에서 발생합니다 ("딥 복사"는 일반적으로 포인터/참조 필드에서 참조되는 각 개체의 복사본을 만드는 것을 의미합니다).

"참조 기준 전달"은 최대의 유연성 (기본 유형 전달과 일관성)을 허용하는 기본값이 아닙니다. 참조로 전달하려는 경우 포인터 (또는 C++에서 참조)를 전달합니다. 성능을 위해서만 사용되는 경우는 const이고 그렇지 않으면 객체 자체를 전달합니다.

+0

p.s. C에는 생성자 자체가 없습니다. C++에서만. C에서 데이터 구조는 단순히 바이트 단위로 복사됩니다. –

+0

@EdwardFalk : 물론, 사실 나는 초기화가 아닌 건설에 대해 이야기했습니다. 또한 "byte-for-byte"것은 표준에 의해 지정되지 않습니다. 실제로는 이름이 지정된 필드 만 복사 할 수 있습니다 ("초기화 후에도 구조체 개체의 명명되지 않은 멤버가 불확정 값을가집니다.", C99 §6.7 .8 ¶9) - 즉, 패딩은 복사되거나 복사되지 않을 수 있습니다. –

+0

큰 설명, 필요한 경우 전체 복사본을 수행하기 위해 기본 동작을 재정의 할 수 없다고 추측합니다. – chrisw

1

예 막대의 로컬 사본이 스택에 푸시됩니다. 나머지는 다음의 작업 예제에 주석 처리됩니다.

#include <stdio.h> 
    struct foo 
    { 
     int a; 
     int *b; 
    } bar; 
    void baz(struct foo qux) 
    { 
     bar.a = 2; // if its a different copy then printf on main should print 1 not 2. 
     *bar.b = 5; // if its a different copy then printf on main should print 5 not 4. since the place pointer pointing to is same 
    } 
    int main(){ 
     bar.a=1; 
     bar.b = (int*)malloc(sizeof(int)); 
     *bar.b = 4; 
     baz(bar); // pass it to baz(). now the copy of bar in the stack which is what baz going to use 
     printf("a:%d | b:%d\n",bar.a,*bar.b); 
     //answer is 2 and 5 
     /*So indeed it does a shallow copy thats why we lost the "4" stored in bar.b it did not created new space in heap to store "5" instead it used the same space that b was pointing to. 
     */ 
    return 0; 
    } 
관련 문제