我确实检查了互联网,但仍有一些不确定因素。
Casting one struct pointer to other - C
http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
(我读到的关于库和二进制兼容性的内容是特定于C ++的)
我的问题可能有一个解决方案,但需要我深入修改我现有的数学和几何库:Typesafe inheritance in C
在C中,将指针强制转换为兼容类型的功能非常方便,例如:
typedef struct s_pnt2
{
t_real x;
t_real y;
} t_pnt2;
typedef struct s_pnt3
{
t_real x;
t_real y;
t_real z;
} t_pnt3;
(已编辑)允许用户将3D点投射到2D点(因为R ^ 2与R ^ 3 的任何超平面同构)
此外:
typedef union u_vec2
{
t_pnt2 carthesian;
t_real matrix[2];
struct
{
t_real rep;
t_real imp;
} rectangular;
struct
{
t_real mod;
t_real arg;
} polar;
} t_vec2;
typedef union u_vec3
{
t_pnt3 carthesian;
t_real matrix[3];
struct
{
t_real rho;
t_real theta;
t_real phi;
} spherical;
struct
{
t_real r;
t_real theta;
t_real z;
} cylindrical;
} t_vec3;
这些联盟允许人们在各种系统中明确表达一个点的坐标,而所使用的空间不大且最重要的是,兼容性仍然存在。
在实现将给定矢量从系统转换到另一个系统的功能时,我偶然发现存储当前系统将是一个好点。所以我创建了一个枚举:
typedef enum e_type
{
CARTHESIAN,
CYLINDRICAL,
SPHERICAL,
POLAR = CYLINDRICAL,
RECTANGULAR = CARTHESIAN
} t_type;
我现在必须存储t_type(int)类型的变量, 并面临一个问题:要么我把它放在最后,要么尺寸之间的兼容性松散:编辑:
+---+ +---+
| x | matches | x |
+---+ +---+
| y | matches | y |
+---+ +---+
| t | doesn't | z |
+---+ +---+
| t |
+---+
或者把它放在开头(就像X11和XEvent一样),与矩阵的松散兼容性,以及(编辑)声明像这样的向量的能力:
t_vec3 vector = (t_vec3){{x, y, z}}
会有更好的方法吗?
即使我在这种情况下不需要它,我也会感兴趣,如果有办法保持二进制兼容性。
更一般地说,欢迎任何关于良好习惯的建议!
感谢您的时间
修改: @llja: 是的我可以做类似
的事情typedef struct s_vec2t
{
t_type type;
t_vec2 p;
} t_vec2t
缺点是:
要访问某些数据,我应该执行以下操作:
t_vec2t point = (t_vec2t){CARTHESIAN, (t_vec2){{x, y}}}
point.p.carthesian.x;
含义我必须使用点修改所有函数,以便它们现在使用类型化点?
答案 0 :(得分:0)
你可以通过继承做的大部分工作,你可以用作文来做。事实上,像clang ++这样的c ++编译器在内部使用组合来实现继承,你将在调试时看到它。
#include <stdio.h>
struct point_1d {
double x;
};
void point_1d_print(struct point_1d const * const point) {
printf("x=%lf", point->x);
}
struct point_2d {
struct point_1d p;
double y;
};
void point_2d_print(struct point_2d const * const point) {
point_1d_print(&point->p);
printf(", y=%lf", point->y);
}
struct point_3d {
struct point_2d p;
double z;
};
void point_3d_print(struct point_3d const * const point) {
point_2d_print(&point->p);
printf(", z=%lf", point->z);
}
void switch_xy(struct point_2d * point) {
double const tmp = point->p.x;
point->p.x = point->y;
point->y = tmp;
}
int main(void) {
struct point_3d point;
// Direct access
point.p.p.x = 1.5;
point.p.y = 2.0;
point.z = 3.0;
// Pretend polymorphism
switch_xy(&point.p);
point_3d_print(&point);
printf("\n");
return 0;
}
当然,您可以组合多个结构来模拟多重继承。派生指向父项的指针(point_3d→point_2d→point_1d)很简单,但是没有安全的方法可以从point_1d返回到point_2d。