假设我有两种不同的结构:
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
}
然而,由于我会重新命名相同的枚举器,编译器将无法工作......有没有办法解决这个问题?
答案 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;