[완료] void* 타입의 인자를 call by reference로 넘길수 있나요?

circle07의 이미지

(질문 수정하였습니다.)

데이터를 얻어오는 함수를
void get(int id, void* p) 로 선언했을때

get 함수 내부에서는 id에 따라 여러 종류의 struct 형태를 인자로 사용하는 p에 저장하고 싶은데
좀처럼 아이디어가 안떠오르네요.

대략 구상한 내용은 아래와 같습니다. 정확한 문법은 아니고 대략 의사코드로 보시면 됩니다.

struct A { .. }
struct B { .. }
struct C { .. }
 
void get(int id, void* p)
{
    struct A aa;
    struct B bb;
    struct C cc;
 
    if(id가 Atype일 경우)
    {
        aa = 특정값1;   // aa 구조체에 특정값을 저장
         // p변수에 aa의 내용을 assign하여 함수 밖에서도 사용하고 싶은데 이부분을 잘 모르겠습니다. 가능한지도 의문이 드네요.
        // p = aa;  <--의미는 대략 이정도..
    }
    else if(id가 Btype인 경우)
    {
        bb = 특정값2;
        p = bb;   <-- 위와 같은 의미
    }
    else if(id가 Ctype인 경우)
        cc = 특정값3;
        p = cc;   <-- 여기도 역시 위와 같은 의미..
    }
}
 
 
main()
{
    int id;
    cin >> id;
 
    void* temp;
    struct A aaa;
    struct B bbb;
    struct C ccc;
 
    if(id가 A타입)
        temp = &aaa;
    else if(B타입)
        temp = &bbb;
    else if(C타입
         temp = &ccc;
 
    get(id,temp)
 
    cout << temp.val;
}

정리하면 함수의 인자로 void*를 사용할때
함수 내에서 인자에 데이터를 저장하면
함수 밖에서 저장된 데이터를 사용할 수 있도록 하는게 목적입니다.
void*와 포인터에 대한 이해가 부족하여 이렇게 질문드립니다.

get함수 밖에서의 temp주소와 함수 내에서의 p의 주소는 같은데,
주소만 가리키고 있어서 실제 데이터를 assign하는것이 가능한지와 가능하다면 처리할수 있는 방법에 대해서 힌트좀 부탁드립니다.

klara의 이미지

적으신 코드를 보니 C의 기본 문법(if문), 변수의 범위(수명), 포인터 사용법(복사, 참조)등을 전부 모르시는 것 같습니다.
그냥 C입문서를 한번 보시는게 좋을듯합니다.

circle07의 이미지

제가 알고싶어하는 답변만 생각하다보니 질문이 너무 성의가 없었나보네요..
수정하도록 하겠습니다.

klara의 이미지

문제는 if 구문 뿐이 아닙니다. 좀더 자세하게 적으면...

1. 포인터의 멤버 참조는 .이 아니라 ->입니다.
(X) temp.val (O) temp->val

2. void*포인터를 그대로 이용하는 것은 불가능합니다. 적당한 형변환이 필요합니다.
(X) temp->val (O) reinterpret_cast<A*%gt;(temp)->val

2. 포인터가 아닌 타입의 변수를 포인터에의 대입하는 것은 불가능합니다. 주소 참조 연산자(&)를 이용해야 합니다.
(X) p = aa (O) p = &aa

3. 함수내에서 선언한 변수는 스택에 들어가며 함수가 종료되면 없어지므로, 함수내에서 할당한 변수를 함수밖에 쓸려면 동적할당을 이용해야 합니다.
(X) A aa (O) A *aa = new A

3. C++코드를 쓰신다면, 어떠한 임의의 타입이라도 무조건 받아내야 하는게 아니라, 규약이 정해져있는 것이라면 가상함수를 이용한 인터페이스를 사용하시는게 좋을 듯합니다.

4. 마지막으로, 반드시 void*가 아니면 받아 낼수 없는 경우, C는 무조건 call by value이기 때문에 이중포인터 혹은 포인터의 레퍼런스를 이용해야 하거나 값을 복사해야합니다. 다만 이경우 값을 복사하는 것은 적당한 대입연산자가 없거나 제대로된 형변환이 불가능한 경우는 잘못된 동작을 할수 있습니다.
(X) void get(int id, void* p) (O) void get(int id, void* &p)

결론: C 와 C++ 입문서를 읽어보세요.

circle07의 이미지

답변 정말 감사드립니다.
질문을 수정했는데도 역시나 많이 부족했나봅니다.
질문할땐 정확하게 써야하는걸 다시한번 배웠습니다..^^;

1. 급하게 질문하느라 의미만 전달하려고 했던것 같습니다.

2-1. 형변환역시 현재 작성하고 있는 코드에서는 적용했는데 이부분도 급하게 하다보니 생각하지 못했던것 같네요.

2-2. 의미가 assign한다는 내용으로 실제로 저렇게 쓰면 안되겠죠..^^;

3-1. 실제 get함수 내에서 동적 할당한 변수를 함수 밖에서 어떻게 사용할수 있는지 잘 모르겠습니다. 함수 내에서 선언한 변수 aa에 저장된 값을 파라미터로 받은 변수 p에 할당하여 함수가 끝난 후에 이 파라미터로 사용한 변수 p의 내용을 가져다 쓰기 위한 내용이었습니다.
main함수의 struct A aaa인 경우에는 동적, 정적 상관이 없는듯 합니다.

3-2. 가상함수를 사용하는것도 고려해봐야겠습니다. 설계한 내용을 다시한번 살펴봐야겠네요.

4. 포인터의 레퍼런스를 사용하는 것으로 일단 동작은 합니다. 당장의 문제는 해결이 되었습니다. 이해하려면 좀더 봐야겠지만요.

기초의 중요성을 다시한번 생각할 수 있는 기회가 되었습니다.
다시한번 감사드립니다.

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.