不同结构的数组

时间:2016-06-10 14:17:45

标签: c struct enums

假设我有两种不同的结构:

typedef struct {
 int a;
 int b;
 int c;
 int d;
} struct_1;

typedef struct {
 int a;
 int b;
 int e;
 int f;
 int g;
 int h;
} struct_2;

并且它们在两种不同的算法中以类似的方式使用。我要做的是用两个基本上不同类型的结构替换dinamic数组,并使用两个枚举来实际需要的情况。目的是保留结构字段的不同名称,而不是使用数字。如下所示:

typedef enum {
 a,
 b,
 c,
 d,
 num1_fields
} struct_1_fields;

typedef enum {
 a,
 b,
 e,
 f,
 g,
 h
 num1_fields
} struct_2_fields;

int *structure;
if(case_1) {
  structure = malloc(4*sizeof(int));
} else if(case_2) {
  structure = malloc(6*sizeof(int));
} else {
 //something else
}

然而,由于我会重新命名相同的枚举器,编译器将无法工作......有没有办法解决这个问题?

5 个答案:

答案 0 :(得分:1)

您可以在C:

上使用OOP方法
  #include <stdio.h>
  #include <stdlib.h>

  // forward declaration for virtual function table
  struct vtable;

  // base class
  typedef struct {
    struct vtable* tbl_;
  } base;

  // virtual function table
  typedef struct vtable {
    void(*method_for_algorithm_1_)(base* object);
    void(*method_for_algorithm_2_)(base* object);
  } vtable;

  // algorithm 1 knowns only about base
  void algorithm_1(base* p[], int size) {
    for (int i = 0; i < size; i++) {
      p[i]->tbl_->method_for_algorithm_1_(p[i]);
    }
  }

  // algorithm 2 knowns only about base
  void algorithm_2(base* p[], int size) {
    for (int i = 0; i < size; i++) {
      p[i]->tbl_->method_for_algorithm_2_(p[i]);
    }
  }

  // struct1 is base
  typedef struct {
    base super_;
    int a;
    int b;
    int c;
  } struct1;

  // struct2 is base
  typedef struct {
    base super_;
    int a;
    int b;
    int c;
    int d;
    int e;
  } struct2;

  void struct1_method_for_algorithm1(base* object) {
    struct1* s1 = (struct1*)object;
    printf("struct1_method_for_algorithm1: %d %d %d\n", s1->a, s1->b, s1->c);
  }
  void struct1_method_for_algorithm2(base* object) {
    struct1* s1 = (struct1*)object;
    printf("struct1_method_for_algorithm2: %d %d %d\n", s1->a, s1->b, s1->c);
  }
  void struct2_method_for_algorithm1(base* object) {
    struct2* s2 = (struct2*)object;
    printf("struct2_method_for_algorithm1: %d %d %d %d %d\n", s2->a, s2->b, s2->c, s2->d, s2->e);
  }
  void struct2_method_for_algorithm2(base* object) {
    struct2* s2 = (struct2*)object;
    printf("struct2_method_for_algorithm2: %d %d %d %d %d\n", s2->a, s2->b, s2->c, s2->d, s2->e);
  }

  int main() {
    {
      vtable struct1vtable = {
        &struct1_method_for_algorithm1,
        &struct1_method_for_algorithm2
      };
      struct1 a[] = {
        { &struct1vtable, 10, 20, 30 },
        { &struct1vtable, 40, 50, 60 },
      };
      base* p[] = { &a[0], &a[1] };
      algorithm_1(p, 2);
      algorithm_2(p, 2);
    }
    {
      vtable struct2vtable = {
        &struct2_method_for_algorithm1,
        &struct2_method_for_algorithm2
      };
      struct2 a[] = {
        { &struct2vtable, 10, 20, 30, 40, 50 },
        { &struct2vtable, 40, 50, 60, 70, 80 },
      };
      base* p[] = { &a[0], &a[1] };
      algorithm_1(p, 2);
      algorithm_2(p, 2);
    }
    return 0;
  }

答案 1 :(得分:0)

如果union适用于您的解决方案

enum struct_types
{
    typ_struct_1,
    typ_struct_2
};

struct struct_1{
 int a;
 int b;
 int c;
 int d;
};

struct struct_2{
 int a;
 int b;
 int e;
 int f;
 int g;
 int h;
};

struct my_struct
{
    uint8_t struct_type;

    union u_members
    {
        struct struct_1 struct_1_typed;
        struct struct_2 struct_2_typed;
        int struct_1_raw[sizeof(struct struct_1)/sizeof(int)];
        int struct_2_raw[sizeof(struct struct_2)/sizeof(int)];
    }members;
};

答案 2 :(得分:0)

也许您可以像这样定义字段偏移:

#!/usr/bin/env python

import numpy as np
import scipy
from sklearn import preprocessing

original = scipy.misc.imread('Crocodylus-johnsoni-3.jpg')
scipy.misc.imshow(original)

transformed = np.zeros(original.shape, dtype=np.float64)

scaler = preprocessing.MinMaxScaler()
for channel in range(3):
    transformed[:, :, channel] = scaler.fit_transform(original[:, :, channel])
scipy.misc.imsave("transformed.jpg", transformed)

答案 3 :(得分:0)

只要普通字段名称共享相同的索引,就可以这样:

enum struct_fields {
    a = 0,
    b, c, d, num1_fields,
    e = 2, f, g, h, num2_fields
};

// if you need distinct names...
typedef enum struct_fields struct1_fields;
typedef enum struct_fields struct2_fields;

因为如果枚举的多个成员具有确定的值是合法的

完成后,您可以安全地执行以下操作:

for (i=0; i<num2_fields; i++) {
    structure[i] = i*2;
}
printf("%d %d %d %d\n", structure[a], structure[b], structure[c], structure[d]);
printf("%d %d %d %d %d %d\n", structure[a], structure[b],
    structure[e], structure[f], structure[g], structure[h]);

得到预期的结果:

0 2 4 6
0 2 4 6 8 10

但永远不要将这些数组别名化为原始结构,因为它会违反严格的别名规则

答案 4 :(得分:0)

正如其他人所提到的,union适用于您想要做的事情。它严格符合C标准。

Per 6.5.2.3结构和工会成员C Standard的第6段:

  

<强>约束

     

...

     

为简化工会的使用,我们做出了一项特殊保证:   如果一个联合包含几个共享共同的结构   初始序列(见下文),以及union对象   目前包含其中一种结构,是允许的   在任何地方检查其中任何一个的共同初始部分   完整的工会类型的声明是可见的。二   如果对应,则结构共享共同的初始序列   成员具有兼容类型(对于位字段,宽度相同)   对于一个或多个初始成员的序列。

例如,X Windows XEvent联盟,defined in X11/Xlib.h

/*
 * this union is defined so Xlib can always use the same sized
 * event structure internally, to avoid memory fragmentation.
 */
typedef union _XEvent {
    int type;       /* must not be changed; first element */
    XAnyEvent xany;
    XKeyEvent xkey;
    XButtonEvent xbutton;
    XMotionEvent xmotion;
    XCrossingEvent xcrossing;
    XFocusChangeEvent xfocus;
    XExposeEvent xexpose;
    XGraphicsExposeEvent xgraphicsexpose;
    XNoExposeEvent xnoexpose;
    XVisibilityEvent xvisibility;
    XCreateWindowEvent xcreatewindow;
    XDestroyWindowEvent xdestroywindow;
    XUnmapEvent xunmap;
    XMapEvent xmap;
    XMapRequestEvent xmaprequest;
    XReparentEvent xreparent;
    XConfigureEvent xconfigure;
    XGravityEvent xgravity;
    XResizeRequestEvent xresizerequest;
    XConfigureRequestEvent xconfigurerequest;
    XCirculateEvent xcirculate;
    XCirculateRequestEvent xcirculaterequest;
    XPropertyEvent xproperty;
    XSelectionClearEvent xselectionclear;
    XSelectionRequestEvent xselectionrequest;
    XSelectionEvent xselection;
    XColormapEvent xcolormap;
    XClientMessageEvent xclient;
    XMappingEvent xmapping;
    XErrorEvent xerror;
    XKeymapEvent xkeymap;
    long pad[24];
} XEvent;

所有各种类型的XEvent都以int type开头,例如:

typedef struct {
    int type;
    unsigned long serial;   /* # of last request processed by server */
    Bool send_event;    /* true if this came from a SendEvent request */
    Display *display;   /* Display the event was read from */
    Window window;
    int width, height;
} XResizeRequestEvent;

typedef struct {
    int type;
    unsigned long serial;   /* # of last request processed by server */
    Bool send_event;    /* true if this came from a SendEvent request */
    Display *display;   /* Display the event was read from */
    Window event;
    Window window;
    Bool override_redirect; /* boolean, is override set... */
} XMapEvent;

事实上,对于大多数int type类型,通用性远远超出XEvent第一个字段。大多数事件类型都以XAnyEvent中的以下字段开头:

typedef struct {
    int type;
    unsigned long serial;   /* # of last request processed by server */
    Bool send_event;    /* true if this came from a SendEvent request */
    Display *display;/* Display the event was read from */
    Window window;  /* window on which event was requested in event mask */
} XAnyEvent;