같은 멤버를 가진다면 A 구조체에서 B 구조체로 묵시적 형변환이 가능한건가요?

dreamist의 이미지

내용물이 같고 이름이 다른 두 구조체를 사용할 때,
B구조체를 입력받는 함수에 A구조체를 넣으면 묵시적 형변환이 되는건가요?

실행에 문제가 없고, 원하던 출력을 보여줘서 형변환이 일어나는 것 같은데
이해가 되지 않네요.

이렇게 같은 내용물을 가지고 있지만 다른 이름을 가진 구조체를 사용하기 위해서는
어떻게 해야되나요?

/* A.h */
#pragma once
#include <stdio.h>
 
typedef struct AaMat{
   int row;
   int col;
} AaMat;
/* B.h */
#pragma once
#include <stdio.h>
 
typedef struct BbMat{
   int row;
   int col;
} BbMat;
 
int GetMatD(BbMat mat);
/* B.c */
#include "B.h"
 
int GetMatD(BbMat mat)
{
   return mat.row*mat.col;
}
/* main.c */
#include "A.h"
#include "B.h"
 
int main(void)
{
   AaMat amat;
   amat.row=3;
   amat.col=2;
 
   printf("D : %d\n",GetMatD(amat));
 
   return 0;
}
dreamist의 이미지

위에 코드를 직접 돌려보니 실행이 안되네요;

그래서 코드를 다시 살펴보니 개념을 가져온 코드에서는
동적할당으로 처리하고, 함수의 입력을 void*로 해서 받았네요;;
그래서 내용물이 같은 구조체의 처리에는 문제가 없다는 것은 알겠는데요

이렇게 같은 내용물을 가지고, 이름이 다른 구조체를 사용할 때,
이렇게 입력을 void* 로 받는 것 말고 다른 방법은 없나요??

익명 사용자의 이미지

C는 이름이나 타입이 아닌 구조를 대입합니다
파스칼이나 Cpp랑은 다르죠

dreamist의 이미지

묵시적 형변환은 여기서 가능하지 않은데,명시적 형변환으로 처리하니까 결과가 나오네요.
C가 이름이나 타입이 아닌 구조를 대입해서 가능한거라고 볼 수 있겠네요.

근데 이런 경우에는 어떻게 하는게 가장 좋나요?

라스코니의 이미지

같은 내용을 가진 구조체를 따로 만들어야할 이유는 딱히 없는 것 같은데요?

dreamist의 이미지

어떤 헤더파일에들서 구조체와 함수를 가져와서 사용해야되는데요.
이렇게 제가 만든 헤더만 가져오면 상관이 없는데 원본 헤더를 가져올 수 있어서요.
그럴때 중복선언 문제가 없고 원본 헤더에 정의된 구조체 이름을 입력으로 받아도 같은 결과가 나와야 되서요.

mirheekl의 이미지

http://stackoverflow.com/questions/479207/function-overloading-in-c

- 매크로
- 별도의 함수
- C++ 사용(...)
- union을 이용한 추가 구조체 선언.
- 최신 컴파일러가 제공하는 확장 기능 사용.

등등..

일단 plain C에서 완벽하게 해결할 방법은 없는 것 같습니다.

아니면, C가 void*에 대해 암묵적 변환을 지원하는 점을 이용해서 그냥 함수자체를 void*를 받게 작성하셔도 되겠습니다. (다만 이경우 컴파일러에서 타입체크를 해주지 못하게 되겠죠.)

#include <stdio.h>
 
typedef struct AaMat{
	int row;
	int col;
} AaMat;
 
typedef struct BbMat{
	int row;
	int col;
} BbMat;
 
int GetMatD(void* pMat)
{
	AaMat *pAMat = pMat;
	return pAMat->row * pAMat->col;
}
 
int main(void)
{
	AaMat amat;
	BbMat bmat;
	amat.row=3;
	amat.col=2;
 
	bmat.row=5;
	bmat.col=7;
 
	printf("D : %d\n",GetMatD(&amat));
 
	printf("D : %d\n",GetMatD(&bmat));
 
	return 0;
}

--

dreamist의 이미지

원본 파일은 이런식으로 작성되어 있더라고요.
void*를 이용해 받아들인 후 어떤 구조체를 입력받은지 확인
그리고 구조체에 따라 명시적 형변환을 해주더라고요.

mirheekl의 이미지

#include <stdio.h>
 
typedef struct AaMat{
	int row;
	int col;
} AaMat;
 
typedef struct BbMat{
	int row;
	int col;
} BbMat;
 
int GetMatD(AaMat mat)
{
	return mat.row * mat.col;
}
 
int GetMatD2(int row, int col)
{
	AaMat mat;
	mat.row = row;
	mat.col = col;
	return GetMatD(mat);
}
 
#define CallGetMatD(X)	(GetMatD2(X.row, X.col))
 
int main(void)
{
	AaMat amat;
	BbMat bmat;
	amat.row=3;
	amat.col=2;
 
	bmat.row=5;
	bmat.col=7;
 
	printf("D : %d\n",CallGetMatD(amat));
 
	printf("D : %d\n",CallGetMatD(bmat));
 
	return 0;
}

여기서 GetMatD2 안에서 굳이 AaMat를 선언할 이유는 없지만 기존에 만들어둔 함수를 편하게 이용하려면 저렇게 하는게 좋겠지요.
호출할 때 넘기는 구조체 종류가 어찌됐든 필요한 필드가 없거나 타입이 다른 경우 컴파일 에러가 발생하므로 쓸만할겁니다. C에는 어쨌든 액세스 모디파이어는 없으니 항상 모든 멤버를 나열하도록 매크로와 중간함수를 작성하면 더욱 편하겠죠. 포인터를 받는 함수일 경우에도 비슷하게 적용가능하고요. 매크로는 기존 함수 개수만큼 필요하겠지만 중간함수는 하나만 있어도 됩니다.

다만 두 구조체가 완전히 동일한 구조체인지는 보장받을 수 없습니다. 예를 들어 새 구조체가 수퍼셋이라든지, 멤버의 순서가 다르게 정의돼있다든지 하면.. 그래도 의미상 문제는 없으나 바이너리 레벨에선 문제의 소지가 있겠지요. 이것까지 보장받으려면 sizeof 비교랑 메모리 비교 등등을 더 넣으시면 됩니다.

--

익명 사용자의 이미지

이렇게 하면 간단히 해결될 것 같습니다만

typedef struct AaMat BbMat;
mirheekl의 이미지

저 시점에서 AaMat가 무조건 정의돼있는 상황이라면 BbMat를 선언할 필요도 없겠죠. 그냥 AaMat만 쓰면 되니까.

그게 보장이 되지 않기 때문에 저런 귀찮은 작업들이 필요해지는 겁니다. 정의될지 안될지, 정의된다 해도 언제 될지도 모르는데 캐스팅 없이 받아내야 하니까.

--

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.