IT이야기

C의 함수에서 '구조물' 반환

cyworld 2022. 4. 24. 09:41
반응형

C의 함수에서 '구조물' 반환

오늘 나는 몇명의 친구들에게 C의 사용법을 가르치고 있었다.structs. 그들 중 한 명이 당신이 a를 돌려줄 수 있는지 물었다.struct내가 대답한 기능에서: "아니오! 당신은 역동적으로 포인터를 돌려줄 것이다.malloc에이드struct대신 s."

C++를 주로 하는 사람으로부터 온 나는 돌아올 수 없을 것으로 예상하고 있었다.structs 값으로C++에서는 과부하 할 수 있다.operator =당신의 물건을 위해 그리고 당신의 물건을 가치로 돌려주는 기능을 가지고 있는 것이 완전히 이치에 맞다.하지만 C에서는 그런 선택권이 없어서 컴파일러가 실제로 무엇을 하고 있는지 생각하게 만들었어.다음을 고려하십시오.

struct MyObj{
    double x, y;
};

struct MyObj foo(){
    struct MyObj a;
    
    a.x = 10;
    a.y = 10;
    
    return a;
}        

int main () {

    struct MyObj a;
    
    a = foo();    // This DOES work
    struct b = a; // This does not work
      
    return 0;
}    

나는 왜 그런지 이해한다.struct b = a;작동하지 않아야 함 - 과부하할 수 없음operator =데이터 유형.어떻게 그럴 수가 있지?a = foo();컴파일은 괜찮니?struct b = a;과 같은 을 던질 수 있다 어쩌면 다음과 같은 질문을 해야 할지도 모른다.정확히 무엇을 말하는가?return와 관련된 한 진술.=사인 do?

할 수 의 구하하하 ( (?=운영子) 문어(文語)文語(는 잘 정립된 부분이다그것은 언어에서 잘 정의된 부분이다.에 대한 유일한 문제struct b = a완전한 유형을 제공하지 않았다는 겁니다.struct MyObj b = a잘 될 거야구조물을 기능에도 전달할 수 있다. 구조물은 매개 변수 전달, 반환 값 및 할당을 위해 내장 유형과 정확히 동일하다.

여기 세 가지를 모두 수행하는 간단한 시연 프로그램이 있는데, 이 프로그램은 구조를 매개 변수로 전달하고, 기능에서 구조를 반환하며, 할당 설명서에 구조를 사용한다.

#include <stdio.h>

struct a {
   int i;
};

struct a f(struct a x)
{
   struct a r = x;
   return r;
}

int main(void)
{
   struct a x = { 12 };
   struct a y = f(x);
   printf("%d\n", y.i);
   return 0;
}

다음 예제는 거의 동일하지만, 내장되어 있는 것을 사용한다.int 프로그램 전달, 할당 에 대해 두 은 동일하다두 프로그램은 매개변수 전달, 할당 등에 대한 값별 전달과 관련하여 동일한 행동을 가진다.

#include <stdio.h>

int f(int x) 
{
  int r = x;
  return r;
}

int main(void)
{
  int x = 12;
  int y = f(x);
  printf("%d\n", y);
  return 0;
}

다음과 같은 전화를 걸 때a = foo();, 컴파일러는 스택에 있는 결과 구조의 주소를 밀어넣고 그것을 에 "poss" pointer로 전달할 수 있다.foo()기는 하다 이 될 수 효과적으로 다음과 같은 것이 될 수 있다.

void foo(MyObj *r) {
    struct MyObj a;
    // ...
    *r = a;
}

foo(&a);

단, 정확한 구현은 컴파일러 및/또는 플랫폼에 의존한다.칼 노룸이 지적하듯이, 구조가 충분히 작다면, 그것은 기록부에 완전히 다시 기록될 수도 있다.

내가 기억하는 한, C의 첫 번째 버전은 프로세서 레지스터에 들어갈 수 있는 값만 반환할 수 있도록 허용했다. 즉, 구조체에 포인터를 반환할 수 있다는 뜻이다.함수 인수에 적용되는 제한과 동일한 제한.

보다 최신 버전에서는 구조체처럼 더 큰 데이터 객체를 전달할 수 있다.나는 이 특징이 이미 80년대나 90년대 초반에 흔했다고 생각한다.

그러나 어레이는 여전히 통과되고 포인터로만 반환될 수 있다.

구조체를 돌려주는 것은 문제가 되지 않는다.그것은 가치로 전달될 것이다.

그러나 로컬 변수의 주소를 가진 구성원이 구조체에 포함된 경우

struct emp {
    int id;
    char *name;
};

struct emp get() {
    char *name = "John";

    struct emp e1 = {100, name};

    return (e1);
}

int main() {

    struct emp e2 = get();

    printf("%s\n", e2.name);
}

자, 여기e1.name함수의 로컬 메모리 주소 포함get(). 한번get()반송하면, 그 지역 주소가 공개되었을 것이다.따라서, 발신자 내에서 우리가 그 주소에 접근하려고 하면, 우리가 자유 주소를 사용하려고 할 때 분할 오류가 발생할 수 있다.그거 안 좋은데..

as thee1.id그 가치가 복사될 것이기 때문에 완벽하게 유효할 것이다.e2.id

따라서, 우리는 항상 함수의 로컬 메모리 주소를 반환하지 않도록 노력해야 한다.

몰로크 처리된 모든 것은 원하는 때에 반환할 수 있다.

struct b구문 오류로 인해 라인이 작동하지 않는다.만약 당신이 타입을 포함하도록 그것을 확장한다면 그것은 잘 될 것이다.

struct MyObj b = a;  // Runs fine

여기서 C가 하고 있는 것은 본질적으로 a이다.memcpy원점에서 목적지까지.이것은 의 할당과 반환 모두에 적용된다.struct 값들)((및 다 모 값 값 값 값 값 )

struct emp {
    int id;
    char *name;
};

struct emp get() {
    char *name = "John";

    struct emp e1 = {100, name};

    return (e1);
}

int main() {

    struct emp e2 = get();

    printf("%s\n", e2.name);
}

새로운 버전의 컴파일러와 잘 어울린다.id와 마찬가지로 이름의 내용이 할당된 구조 변수에 복사된다.

그래, 구조와 반환 구조도 통과할 수 있어.네 말이 맞았지만 실제로 MyObj b = a와 같아야 할 데이터 유형을 통과하지 못했다.

사실 나도 포인터나 전역 변수를 사용하지 않고 기능에 대한 둘 이상의 값을 반환할 수 있는 더 나은 해결책을 찾으려 할 때 알게 되었다.

다음은 평균에 대한 학생 점수의 편차를 계산하는 동일한 예다.

#include<stdio.h>
struct marks{
    int maths;
    int physics;
    int chem;
};

struct marks deviation(struct marks student1 , struct marks student2 );

int main(){

    struct marks student;
    student.maths= 87;
    student.chem = 67;
    student.physics=96;

    struct marks avg;
    avg.maths= 55;
    avg.chem = 45;
    avg.physics=34;
    //struct marks dev;
    struct marks dev= deviation(student, avg );
    printf("%d %d %d" ,dev.maths,dev.chem,dev.physics);

    return 0;
 }

struct marks deviation(struct marks student , struct marks student2 ){
    struct marks dev;

    dev.maths = student.maths-student2.maths;
    dev.chem = student.chem-student2.chem;
    dev.physics = student.physics-student2.physics; 

    return dev;
}

collelege stack을 위해 arg로 푸시된 구조 var e2 어드레스를 거기에 할당한다.실제로 get()은 eax reg에서 e2의 주소를 반환한다.이것은 참고가 되는 호출과 같다.

C에서 구조체를 지정할 수 있다. a = b;유효한 구문이다.

당신은 그저 당신의 라인에서 타입의 일부 -- 구조 태그 -- 를 그냥 빼놓았을 뿐이다.

참조URL: https://stackoverflow.com/questions/9653072/return-a-struct-from-a-function-in-c

반응형