C에서 함수명 중복에 관한 질문입니다.

runafter의 이미지

제가 하나의 프로그램에서
데이터형만 다른 스택을 2개 사용하려고 합니다.

처음 스택 구현할때
데이터형을 매크로로 저의 해 놔서
따로따로 사용할때에는 매크로변수면 변경하면
다른 코드들은 거의 변경없이 사용할수 있었습니다.

그런데!!

하나의 프로그램에서 같이 사용하다보니
매크로변수부터 시작해서 모든 함수명이 겹칩니다.

이것을 해결할 방법이 없을까요?
데이터형마다 다른 이름의 함수들을 다 만들어줘야 하나요?

다음은 제가 만들고 있는 프로그램에서 스택이 필요한 부분입니다
쓰레드풀을 만들고 있는데
쓰레드풀에는 쓰레드정보를 갖고있는 스택과
메모리풀이 필요합니다.
그런데 메모리풀안에
할당 가능한 주소값을 저장하는 스택이 또 존재합니다.

두가지 스택에서의 차이점은 데이터형밖에 없습니다.

좋은 해결책 부탁드립니다. ㅠㅠ

코퍼스의 이미지

쓰신 글만 읽어서는 잘 감이 안오는데..
처음부터 데이터 타입을 void * 형으로만 되는 것 아닌가요?
그리고, type 에 대한 값을 담아두는 변수를 하나 추가해서 처리하면 될 것 같은데요..

A few Good Man

익명 사용자의 이미지

runafter wrote:
...
데이터형마다 다른 이름의 함수들을 다 만들어줘야 하나요?
...
두가지 스택에서의 차이점은 데이터형밖에 없습니다.

C에서 C++의 템플릿을 흉내 낼려고 하시나요???

runafter의 이미지

거의 같은 코드를 함수이름때문에
다시 작성하는것이 너무 비효율적으로 생각되서요..

제가 두가지 방법을 생각해 봤는데요 실제로는 구현해 보지않았고
검증도 되지 않은것입니다.

첫번째는 #define와 ##를 이용해 함수 이름앞이나 뒤에
추가되는 이름을 붙여주는 것이고요

두번째는 스택관련코드와 실재로 사용하는코드를 같은 파일에 넣고
함수명앞에 static을 넣어 extern이 안되게 하는것입니다

밑에 코드를 추가합니다

      1 #ifndef     _TINY_STACK
      2 #define     _TINY_STACK
      3
      4 #define     TS_ERROR_NOTMALLOC      -1
      5 #define     TS_ERROR_STACK_FULL     -2
      6 #define     TS_ERROR_STACK_EMPTY    -3
      7
      8
      9 typedef     void*           STACK_DATA;
     10 typedef     unsigned int    STACK_INDEX;
     11
     12 struct tiny_stack{
     13 STACK_DATA*     pData;
     14 STACK_INDEX     sp;
     15 STACK_INDEX     size;
     16 };
     17
     18 int ts_init(struct tiny_stack* stack,unsigned int size);
     19 int ts_push(struct tiny_stack* stack,STACK_DATA data);
     20 int ts_pop(struct tiny_stack* stack,STACK_DATA* pdata);
     21 int ts_destroy(struct tiny_stack* pstack);
     22
     23
     24 #endif

이것이 쓰레드 정보를 저장할 스택입니다
void*형을 저장합니다
실제로는 다른 구조체의 포인터가 사용됩니다.

      1 #ifndef     _TINY_STACK_H
      2 #define     _TINY_STACK_H
      3
      4 #define     TS_ERROR_NOTMALLOC      -1
      5 #define     TS_ERROR_STACK_FULL     -2
      6 #define     TS_ERROR_STACK_EMPTY    -3
      7
      8 #include "../mpooldef.h"
      9 typedef     MPOOL_DATA_TYPE*        STACK_DATA;
     10
     11 struct tiny_stack{
     12 STACK_DATA*     pData;
     13 unsigned int    sp;
     14 unsigned int    size;
     15 };
     16
     17 int ts_init(struct tiny_stack* stack,unsigned int size);
     18 int ts_push(struct tiny_stack* stack,STACK_DATA data);
     19 int ts_pop(struct tiny_stack* stack,STACK_DATA* pdata);
     20 int ts_destroy(struct tiny_stack* pstack);
     21
     22
     23 #endif

이것은 메모리풀에서 사용되는 스택입니다.
내부구현코드는 전혀 변경된 것이 없습니다.

mpooldef.h 파일입니다

      1 #ifndef         _MPOOLDEF_H
      2 #define         _MPOOLDEF_H
      3 #include "../tpooldef.h"
      4 typedef     struct _task    MPOOL_DATA_TYPE;
      5
      6 #endif

tpooldef.h 파일입니다.

      1 #ifndef     _TASK_H
      2 #define     _TASK_H
      3 /* 작업큐에 들어가 각 쓰레드들이 이 구조체의 내용에 따라 함수 실행 */
      4 /* work_func : 쓰레드가 실제로 수행할 작업 */
      5 /* 이 함수의 인자인 arg는 이 구조체에서*/
      6 /* union _arg arg의 포인터이다 */
      7 /* 함수 내에서 사용할 때에는 */
      8 /* 사용하고자 하는 데이터타입으로 캐스팅후 사용 */
      9
     10 struct _task{
     11     void* (*work_func)(void* arg);
     12     union _arg{
     13         void* arg;
     14         // work_func의 argument로 사용할
     15         // 데이터타입을 추가
     16         // 단 그 데이터타입은 work_func에서 사용할 때
     17         // 포인터로 접근 가능하고 캐스팅이 필요하다.
     18     }arg;
     19 };
     20
     21 #define     TASK_BUF_SIZE   100
     22 #endif

여기에서 주석은 무시해주시고;;(제가 까먹을까봐 적어논 것입니다)

실제로 사용될때에는 union안에 여러 구조체나 변수가 들어갑니다.
(메모리풀에서 쓰일 실제데이터들입니다.)

그리고 코퍼스님의 말대로 void*형으로 하면 되지만
저는 다음과 같은 코드를 사용하고 싶습니다. ㅠㅠ

     17 int mempool_stack_init(struct mempool* mp)
     18 {
     19     MPOOL_DATA_TYPE* p=mp->pData+mp->reserve_size-1;
     20     MPOOL_DATA_TYPE* base=mp->pData-1;
     21     int ret=ts_init(&mp->stack_pool,mp->reserve_size);
     22     for(;p>base;p--){
     23         ts_push(&mp->stack_pool,p);
     24     }
     25     return ret;
     26 }

결국 방법이 없다면 이런방식의 코딩은 포기하고 그냥
void*형으로 써야겠네요.

C++의 template나 namespace의 필요성을 절실히 느끼는군요 ㅠㅠ

runafter의 이미지

일단 사과드립니다.
스택에서 쓰는것과 제가 마지막에 올린 코드는 상관이 없네요.

그래도 이왕에 글을 올렸으니

동일함수명을 피하는 방법이라던지
거의 비슷한 코드를 최대한 코드수정없이 사용할수 있는 방법이
있다면 가르쳐 주셨으면 합니다.
(큐, 스택, 리스트 등)

dotri의 이미지

문의하신 내용이 void형 포인터가 존재하는 이유입니다. void형 포인터를 사용해서 서로 다른 데이터형간에도 적용할 수 있는 범용 인터페이스를 만드시는게 정석입니다. ANSI-C 표준인지는 모르겠으나.. 볼랜드사의 Turbo-C 컴파일러에는 void *형으로 정의된 각종 자료구조와 정렬,탐색 알고리즘이 이미 인터페이스로 명시되어 있습니다. 아마 Gnu Compiler Collection 에도 있지 않을까 추정되네요.

runafter의 이미지

제가 한동안 C++쪽만 공부하다보니
너무 template과같은 편리한 것에만 길들여져있어
void*의 좋은 기능을 잠시 잊고 있었던것 같습니다.

lifthrasiir의 이미지

dotri wrote:
문의하신 내용이 void형 포인터가 존재하는 이유입니다. void형 포인터를 사용해서 서로 다른 데이터형간에도 적용할 수 있는 범용 인터페이스를 만드시는게 정석입니다. ANSI-C 표준인지는 모르겠으나.. 볼랜드사의 Turbo-C 컴파일러에는 void *형으로 정의된 각종 자료구조와 정렬,탐색 알고리즘이 이미 인터페이스로 명시되어 있습니다. 아마 Gnu Compiler Collection 에도 있지 않을까 추정되네요.

혹시 qsort나 bsearch 같은 건가요? 그럼 ANSI C에도 있습니다. 단 실제 형식을 알고 있는 callback 함수가 있어야 하고 한 element가 몇 바이트인지는 알아야 합니다. C에서 C++ 비슷하게 쓰기 위한 일종의 방법이죠.

- 토끼군

댓글 달기

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