2

質問Passing variable type as function parameterへの回答に基づいて:

私は次のように書くことができます:

enum {
    TYPEA,
    TYPEB,
    TYPEC,
    TYPED
} TYPE;

void foo(TYPE t, void* x){
    switch(t){
        case TYPEA:
            struct A* y = (struct A*)x;
                            //do something with a member named "next"   
            break;
        case TYPEB:
            struct B* y = (struct B*)x;
                            //do something with a member named "next" 
         ...
    }
}

「次の名前のメンバーを持つもの」を複数回書き直さないようにする方法はありますか?

A と B の "next" は、各構造体の同じ相対メモリ位置にないと想定しています。

4

4 に答える 4

2

列挙型の項目にカスタム番号が指定されていないと仮定すると、関数ポインターを使用して、switch ステートメントのコンパクト バージョンを実行できます。

enum {
    TYPEA,
    TYPEB,
    TYPEC,
    TYPED,

    TYPE_N // number of enum items
} TYPE;


typedef void(*type_func_t)(void*);



static void TYPEA_specific (void* x) 
{
  struct A* y = x;

  // specific stuff related to TYPEA here

  do_something_with_next(y->next);
}

static void TYPEB_specific (void* x) 
{
  struct B* y = x;

  // specific stuff related to TYPEB here

  do_something_with_next(y->next);
}



static const type_func_t TYPE_HANDLER [TYPE_N] = 
{
  TYPEA_specific,
  TYPEB_specific
  ...
};


inline void foo (TYPE t, void* x)
{
  TYPE_HANDLER[t](x);
}
于 2012-12-07T12:53:11.417 に答える
1

このソリューションでは、マクロを使用します。

#include <stdio.h>

#define POLYCAST_AB(etype, target, member) \
  *((etype) == TYPEA ? &((struct A *)(target))->member :  \
    (etype) == TYPEB ? &((struct B *)(target))->member : 0)

enum TYPE {
   TYPEA,
   TYPEB
};

struct A {
   int next;
} a = {42};

struct B {
   int i;
   int next;
} b = {43, 44};

static void foo(enum TYPE t, void *x) {
   POLYCAST_AB(t, x, next) += 100;  // <-- most other answers can't do this
   printf("next=%d\n", POLYCAST_AB(t, x, next));
}

int main(void) {
   foo(TYPEA, &a);   
   foo(TYPEB, &b);   
   return 0;
}

左辺値が必要ない場合は、マクロ定義で余分な*andを省略できます (また、すべてが同じ型&であるという仮定も省略できます)。next

于 2012-12-07T15:09:13.140 に答える
0

それぞれで、 withcaseのアドレスを取得し、それを関数に渡すか、ポインタを使用して。で何かを行うコードに制御を移すことができます。これは、場所が異なる場合でも、それぞれに同じタイプがあることを前提としています。next&y.nextnextnextstruct

次に3つの例を示します。

// Example 0:  Functional call.
switch(t)
{
    case TYPEA:
        MyFunction(&(struct A *)x->next);
        break;
    case TYPEB:
        MyFunction(&(struct B *)x->next);
        break;
}

// Example 1: Code after the switch.
TypeOfNext *next;
switch(t)
{
    case TYPEA:
        next = &(struct A *)x->next;
        break;
    case TYPEB:
        next = &(struct B *)x->next;
        break;
}
… code that uses next…

// Example 2: Code in the switch, with goto.
switch(t)
{
    TypeOfNext *next;
    case TYPEA:
        next = &(struct A *)x->next;
        goto common;
    case TYPEB:
        next = &(struct B *)x->next;
    common:
        … code that uses next…
        break;
}
于 2012-12-07T12:40:58.313 に答える
0

もちろん、Cには構造体メンバーの動的ルックアップはありません。

ほとんどのキーストロークを節約する解決策は、おそらくマクロを使用することです。

また、から変換するときにポインタをキャストしても意味がありませんvoid *

于 2012-12-07T10:03:10.983 に答える