C에서 한 구조체를 다른 구조체에 할당


146

다음과 같이 구조체의 한 인스턴스를 다른 인스턴스에 할당 할 수 있습니까?

struct Test t1;
struct Test t2;
t2 = t1;

나는 그것이 간단한 구조에서 작동하는 것을 보았습니다 .bu는 복잡한 구조에서 작동합니까?
컴파일러는 유형에 따라 데이터 항목을 복사하는 방법 (예 : int및 문자열 구분)을 어떻게 알 수 있습니까?

답변:


151

구조가 동일한 유형이면 예입니다. 메모리 사본으로 생각하십시오.


72
딥 카피가 없으며 메모리가 복사되지 않았 음을 나타냅니다.
Georg Schölly

3
동시성도 문제입니다.
Tim Post

16
@Tim Concurrency는 정수 및 복식과 같은 내장 유형을 할당하는 것보다 더 이상 문제가되지 않습니다. 할당은 이것들에 대한 원자 연산이 아닙니다.

2
복사가 생성되면 나중에 free ()로 메모리를 비울 수 있습니까?
Betlista

5
@Betlista 자동 변수이기 때문에 free ()로 메모리를 해제 할 수 없습니다 : en.wikipedia.org/wiki/Automatic_variable
joshdoe

138

예, 구조체에 할당이 지원됩니다. 그러나 문제가 있습니다.

struct S {
   char * p;
};

struct S s1, s2;
s1.p = malloc(100);
s2 = s1;

이제 두 구조체의 포인터가 동일한 메모리 블록을 가리 킵니다. 컴파일러는 지정된 메모리를 복사하지 않습니다. 어떤 구조체 인스턴스가 데이터를 소유하는지 알기가 어렵습니다. 이것이 C ++이 사용자 정의 가능한 할당 연산자 개념을 발명 한 이유입니다.이 경우를 처리하기 위해 특정 코드를 작성할 수 있습니다.


1
그것을 읽으면 내 자신의 대답에서 오류 / 누락을 깨닫게했기 때문에 그것을 올렸습니다.
Clifford

1
실제로 복사가 진행되고 있지 않다는 점에 +1.
Tom Duckering

14
스팸으로 신고 된 이유는 무엇입니까? 누군가 마우스 제어권을 상실 했습니까?
Georg Fritzsche

@gf 그리고 명백하게 공격적인 것!

2
@rahmanisback anon의 대답은이 주제에 대해 분명하다 : "컴파일러는 지정된 데이터를 복사하지 않는다 ". struct자체 의 데이터 가 명확하게 복사됩니다.
Tobias

24

먼저이 예제를보십시오.

간단한 C 프로그램의 C 코드는 다음과 같습니다.

struct Foo {
    char a;
    int b;
    double c;
    } foo1,foo2;

void foo_assign(void)
{
    foo1 = foo2;
}
int main(/*char *argv[],int argc*/)
{
    foo_assign();
return 0;
}

foo_assign ()에 해당하는 ASM 코드는 다음과 같습니다.

00401050 <_foo_assign>:
  401050:   55                      push   %ebp
  401051:   89 e5                   mov    %esp,%ebp
  401053:   a1 20 20 40 00          mov    0x402020,%eax
  401058:   a3 30 20 40 00          mov    %eax,0x402030
  40105d:   a1 24 20 40 00          mov    0x402024,%eax
  401062:   a3 34 20 40 00          mov    %eax,0x402034
  401067:   a1 28 20 40 00          mov    0x402028,%eax
  40106c:   a3 38 20 40 00          mov    %eax,0x402038
  401071:   a1 2c 20 40 00          mov    0x40202c,%eax
  401076:   a3 3c 20 40 00          mov    %eax,0x40203c
  40107b:   5d                      pop    %ebp
  40107c:   c3                      ret    

할당이 어셈블리에서 "mov"명령어로 대체 된 것을 볼 수 있듯이 할당 연산자는 단순히 한 메모리 위치에서 다른 메모리 위치로 데이터를 이동하는 것을 의미합니다. 할당은 구조의 즉각적인 멤버에 대해서만 수행되며 구조에 복잡한 데이터 유형이있는 경우 복사에 실패합니다. 여기서 COMPLEX는 목록을 가리키는 포인터 배열을 가질 수 없음을 의미합니다.

구조 내 문자 배열은 대부분의 컴파일러에서 작동하지 않습니다. 할당은 데이터 유형을 복잡한 유형으로 보지 않고도 복사를 시도하기 때문입니다.


2
어떤 조건이 실패하는지 설명 할 수 있습니까? 그것이 항상 저에게 효과적이라고 생각합니다
AlphaGoku

15

이것은 당신이하는 것처럼 간단한 사본입니다 memcpy()(실제로 일부 컴파일러는 실제로 memcpy()해당 코드 에 대한 호출을 생성합니다 ). C에는 "문자열"이 없으며 한 묶음에 대한 포인터 만 있습니다. 소스 구조에 그러한 포인터가 포함되어 있으면 문자 자체가 아니라 포인터가 복사됩니다.


OK, 컴파일러가이 변환 때문에 memcpy여기를 참조 : godbolt.org/z/nPxqWc를 -하지만 지금은 동일한 포인터를 전달하는 경우 ab, 그리고 *a = *bA를 번역 memcpy때문에 들어 정의되지 않은 동작입니다 memcpy"메모리 영역해야하지 중복." (man 페이지에서 인용). 그렇다면 컴파일러를 사용하는 memcpy것이 잘못되었거나 그러한 과제를 작성하는 데 잘못되어 있습니까?
사용자가 아닌 사용자

6

실수와 허수 부분이있는 복소수에서와 같이 "복잡"을 의미 했습니까? "복잡함"은 C 언어와 관련하여 아무것도 의미하지 않으므로 예를 들어야 할 필요는 없습니다.

구조의 직접 메모리 사본을 얻게됩니다. 그것이 원하는 것인지는 구조에 달려 있습니다. 예를 들어 구조체에 포인터가 포함 된 경우 두 복사본 모두 동일한 데이터를 가리 킵니다. 이것은 당신이 원하는 것일 수도 아닐 수도 있습니다. 그것은 당신의 프로그램 디자인에 달려 있습니다.

'스마트'복사 (또는 '딥'복사)를 수행하려면 복사를 수행하는 기능을 구현해야합니다. 구조체 자체에 포인터를 포함하는 포인터와 구조체가 포함되어 있고 이러한 구조체에 대한 포인터 ( "복잡한"이라는 의미)가 포함되어 있고 유지 관리하기 어려운 경우에는 달성하기가 매우 어려울 수 있습니다. 간단한 해결책은 C ++을 사용하고 각 구조 또는 클래스에 대해 복사 생성자와 할당 연산자를 구현 한 다음 각각 고유의 복사 의미를 담당하고 할당 구문을 사용할 수 있으며 더 쉽게 유지 관리하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.