오늘 저는 두 친구에게 C 사용법을 가르치고있었습니다 struct
. 당신이를 반환 할 수 있다면 그 중 하나가 물었다 struct
“아니 당신은 동적으로의 포인터 반환 것! 내가 대답되는 함수에서 malloc
에드struct
대신 합니다.”
주로 C ++을 수행하는 사람에게서 왔으므로 struct
값으로 s 를 반환 할 수 없을 것으로 기대 했습니다. 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
과 같습니다.=
서명 하는가?
[편집] : 좋아, 방금 지적한 struct b = a
것은 구문 오류입니다. 맞습니다. 그리고 저는 바보입니다! 그러나 그것은 훨씬 더 복잡합니다! 사용 struct MyObj b = a
은 실제로 작동합니다! 내가 여기서 무엇을 놓치고 있습니까?
답변
=
문제없이 함수에서 구조를 반환하거나 연산자를 사용할 수 있습니다. 언어의 잘 정의 된 부분입니다. 유일한 문제 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();
컴파일러 는 스택에 결과 구조 의 주소 를 푸시하고 이를 foo()
함수에 대한 “숨겨진”포인터로 전달할 수 있습니다. 효과적으로 다음과 같이 될 수 있습니다.
void foo(MyObj *r) {
struct MyObj a;
// ...
*r = a;
}
foo(&a);
그러나 이것의 정확한 구현은 컴파일러 및 / 또는 플랫폼에 따라 다릅니다. Carl Norum이 언급했듯이 구조가 충분히 작 으면 레지스터로 완전히 다시 전달 될 수도 있습니다.
답변
struct b
는 구문 오류 때문에 라인이 작동하지 않습니다. 유형을 포함하도록 확장하면 제대로 작동합니다.
struct MyObj b = a; // Runs fine
여기서 C는 기본적으로 memcpy
소스 구조체에서 대상까지입니다. 이것은 struct
값의 할당과 반환 모두에 해당 하며 실제로 C의 다른 모든 값에도 적용됩니다.
답변
그렇습니다, 우리는 구조체와 리턴 구조체도 전달할 수 있습니다. 당신이 옳았지만 실제로이 구조체와 같은 데이터 유형을 전달하지 못했습니다. 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;
}
답변
내가 기억할 수있는 한, C의 첫 번째 버전은 프로세서 레지스터에 맞는 값만 반환 할 수있었습니다. 즉, 구조체에 대한 포인터 만 반환 할 수 있습니다. 함수 인수에도 동일한 제한이 적용됩니다.
최신 버전에서는 구조체와 같은 더 큰 데이터 객체를 전달할 수 있습니다. 이 기능은 80 년대 또는 90 년대 초에 이미 일반적이었다고 생각합니다.
그러나 배열은 여전히 포인터로 전달 및 반환 될 수 있습니다.
답변
C 로 구조체를 할당 할 수 있습니다a = b;
. 유효한 구문입니다.
작동하지 않는 라인에서 유형의 일부 (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);
}
이제 e1.name은 get () 함수에 로컬 인 메모리 주소를 포함합니다. get ()이 반환되면 name의 로컬 주소가 해제됩니다. 따라서 발신자가 해당 주소에 액세스하려고 시도하면 해제 된 주소를 시도 할 때 세그먼트 오류가 발생할 수 있습니다. 그건 나빠..
e1.id는 값이 e2.id에 복사되므로 완벽하게 유효합니다.
따라서 항상 함수의 로컬 메모리 주소를 반환하지 않도록 노력해야합니다.
malloced는 무엇이든 원할 때 반환 할 수 있습니다