함수는 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()
돌아가다.
확실히 중요한 것을 놓치고 있는 것 같습니다, 자세한 설명이 도움이 될 것 같습니다.:)
편집: 기타 답변 참조:
자세한 내용은 호출 규약에 따라 크게 다릅니다.일부 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
'itsource' 카테고리의 다른 글
Java의 컨스트럭터는 프라이빗하게 할 수 있습니까? (0) | 2022.08.15 |
---|---|
C#과 Java의 주요 차이점은 무엇입니까? (0) | 2022.08.15 |
약속의 then()을 커밋하면 Vuex3 변환이 작동하지 않음 (0) | 2022.08.14 |
Vue 저장소 어레이 선언의 "Not assignable to type never" TS 오류 (0) | 2022.08.14 |
VueJs, 계산된 자산과 감시자의 차이점? (0) | 2022.08.14 |