itsource

함수는 C에서 구조 변수를 실제로 어떻게 반환합니까?

mycopycode 2022. 8. 14. 11:51
반응형

함수는 C에서 구조 변수를 실제로 어떻게 반환합니까?

킥 스타트만으로 함수의 반환값을 명확하게 알 수 있는 방법:

int f()
{
  int a = 2;
  return a;
}

지금이다a스택내의 메모리를 취득해, 그 라이프 스팬은,f()값을 반환하기 위해 발신자가 값을 배치한 것을 알기에 값을 호출자에 의해 읽히는 특별한 레지스터에 복사합니다.(반환값 보유자 특별 레지스터 크기가 제한되어 있기 때문에 큰 오브젝트를 반환할 수 없습니다.따라서 고급 언어의 경우 오브젝트 함수를 반환하고 싶을 때Ctical로 히프에 있는 객체의 주소를 해당 특수 레지스터에 복사합니다.)

포인터가 아닌 구조 변수를 반환하는 경우 C로 돌아갑니다.

struct inventory
{
    char name[20];
    int number;
};
struct inventory function();

int main()
{
    struct inventory items;
    items=function();
    printf("\nam in main\n");
    printf("\n%s\t",items.name);
    printf(" %d\t",items.number); 
    getch();
    return 0;
}

struct inventory function()
{
    struct inventory items;
    printf(" enter the item name\n ");
    scanf(" %s ",&items.name );
    printf(" enter the number of items\n ");
    scanf("%d",&items.number );
    return items;
}

코드 분기원: https://stackoverflow.com/a/22952975/962545

이렇게 하자

메인부터 시작하죠items변수가 선언되었지만 초기화되지 않은 경우 함수를 호출하여 초기화된 구조 변수를 반환하고 기본 변수에 복사됩니다.지금 나는 어떻게 하는지 이해하기에는 좀 애매하다.function()반환된 구조 변수items이것은 동적으로 생성되지 않기 때문에(기술적으로는 힙에 포함되지 않음), 이 변수의 수명은function()본문, 변수의 크기item특수 레지스터에 들어가지 않을 만큼 충분히 클 수 있는데 왜 작동했을까요?(내부 함수의 아이템을 동적으로 할당하여 주소를 반환할 수 있는 것은 알고 있습니다만, 다른 것은 필요 없습니다.설명 부탁드립니다.)

질문:작동하지만 어떻게 작동합니까?function() 실제로 구조변수가 반환되어 복사됩니다.items그것이 언제 죽어야 하는지 주로 변한다function()돌아가다.

확실히 중요한 것을 놓치고 있는 것 같습니다, 자세한 설명이 도움이 될 것 같습니다.:)

편집: 기타 답변 참조:

  1. https://stackoverflow.com/a/2155742/962545
  2. 반환값 최적화로 명명됨

자세한 내용은 호출 규약에 따라 크게 다릅니다.일부 ABI는 전체 구조를 전달하기 위한 호출 규칙을 가지고 있지 않으며, 이 경우 컴파일러는 자신이 타당하다고 생각하는 모든 작업을 자유롭게 수행할 수 있습니다.

예를 들어 다음과 같습니다.

  • 전체 구조를 연속 레지스터로 전달 및 반환(흔히 "작은" 구조와 함께 사용됨)
  • 전체 구조체를 인수 블록으로 스택에 배치
  • 구조체를 유지할 수 있을 만큼 충분히 큰 빈 인수 할당, 반환값으로 채워짐
  • 것(가 선언된 )void function(struct inventory *))

이러한 실장은 모두, 여기서의 C사양에 준거하고 있는 경우가 있습니다.구체적인 실장에 대해 살펴보겠습니다.GCC ARM 크로스 컴파일러의 출력입니다.

당신이 준 코드를 컴파일하면 다음과 같은 정보를 얻을 수 있습니다.

main:
    stmfd   sp!, {fp, lr}
    add fp, sp, #4
    sub sp, sp, #48
    sub r3, fp, #52
    mov r0, r3
    bl  function(PLT)

수신처 오퍼랜드는 항상 왼쪽에 있습니다.은 스택스페이스를후를 「」로을 알 수 .r0(ARM EABI の ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( 。 function는 인수를 받지 않기 때문에 이 주장은 분명히 컴파일러에 의해 추가된 인위적인 주장입니다.

function음음음같 뭇매하다

function:
    stmfd   sp!, {r4, fp, lr}
    add fp, sp, #8
    sub sp, sp, #36
    str r0, [fp, #-40]
    ldr r3, .L6

        ...
    add r2, pc, r2
    mov r0, r2
    mov r1, r3
    bl  scanf(PLT)
    ldr r3, [fp, #-40]
    mov ip, r3
    sub r4, fp, #36
    ldmia   r4!, {r0, r1, r2, r3}
    stmia   ip!, {r0, r1, r2, r3}
    ldmia   r4, {r0, r1}
    stmia   ip, {r0, r1}
    ldr r0, [fp, #-40]
    sub sp, fp, #8
    ldmfd   sp!, {r4, fp, pc}

는 기본적으로 단일 를 에 합니다.[fp, #-40]나중에 로딩하여 가리키는 주소로 데이터 저장을 시작합니다.됩니다.r0를 ★★★★★★★★★★★★★★★★★★★★★★로 만들었습니다.

struct inventory *function(struct inventory *)

여기서 반환된 구조는 발신자에 의해 스택에 할당되어 전달된 후 반환됩니다.

적어도 큰 구조체는 스택에 할당되어 반환되며, 발신자에 의해 스택에서 팝오프됩니다.컴파일러는 발신자가 이것을 찾을 것으로 예상되는 같은 장소에 그것을 할당하려고 합니다만, 그것이 가능하지 않은 경우는 카피를 작성합니다.레지스터를 통해 반환되는 구조에 대한 포인터가 있는 은 가능하지만 반드시 필요한 것은 아닙니다.

물론 자세한 내용은 아키텍처에 따라 달라집니다.

당신은 C의 물건 넘기기/되돌리기 방식에서 가장 명백한 것을 놓치고 있다: 모든 것은 가치로 돌아간다, 혹은 적어도 그렇게 행동한다.

즉, 다음과 같습니다.

struct foo some_f( void )
{
    struct foo local = {
       .member = 123,
       .bar = 2.0
    };
    //some awsome code
    return local;
}

잘 될 거야, 괜찮아.구조가 작을 경우, 이 코드가 로컬 구조 변수를 생성하여 해당 구조의 복사본을 호출자에게 반환할 수 있습니다.
다른 이 으로 : 、 , 、 른 、 른 、 른 、 른 음 른 음 음 음 : : : : : : : : : : : : : : : : : : : : : :

void caller()
{
    struct foo hidden_stack_space;
    struct foo your_var = *(some_f(&hidden_stack_space));
}
//and the some_f function will behave as:
struct foo * some_f(struct foo * local)
{
    //works on local and
    return local;
}

항상 일어나는 아니지만 결국 이렇게 되는 거야결과는 동일하지만 이 경우 컴파일러의 동작이 다를 수 있습니다.

결론은 C는 값으로 반환되므로 코드는 정상적으로 동작합니다.
단, 다음과 같은 함정이 있습니다.

struct foo
{
    int member1;
    char *str;
};
struct foo some_f()
{
    char bar[] = "foobar";
    struct foo local = {
        .member1 = 123,
        .str = &bar[0]
    };
    return local;
}

가 ": "에 할당되어 있습니다.local.str는 구조가 반환되면 해제되는 메모리를 가리킵니다.이 경우, 이 코드에서 예상되는 문제는 사실입니다.즉, 그 메모리는 더 이상 유효하지 않습니다(또는 더 이상 유효하지 않습니다).
단순히 포인터는 이 mem 주소인 변수이며 그 값이 반환/할당되기 때문입니다.

언급URL : https://stackoverflow.com/questions/22957175/how-does-function-actually-return-struct-variable-in-c

반응형