用于迭代像数组一样的struct成员的C方法?

zeb*_*und 5 c iteration vector subscript memory-address

假设我有一个矢量类:

typedef struct vec3_s
{
    float x, y, z;
}
vec3;
Run Code Online (Sandbox Code Playgroud)

但是,我希望能够迭代它而不将其转换为浮点数组.虽然在这种情况下演员阵容是可以接受的,但我很想知道C++中的任何功能是否都可以在C语言中完成.例如,在C++中,由于std::vector< T >下标[]运算符被重载,我可以传递其地址一个函数的第一个索引void*.

void do_something_with_pointer_to_mem( void* mem )
{
    // do stuff
}

int main( void )
{
    std::vector< float > v;

    // fill v with values here

    // pass to do_something_with_pointer_to_mem

    do_some_with_pointer_to_mem( &v[ 0 ] );

    return;
}
Run Code Online (Sandbox Code Playgroud)

另一个更具体的例子是在OpenGL中使用glBufferData(...)时(使用C++时):

glBufferData( GL_ARRAY_BUFFER, sizeof( somevector ), &somevector[ 0 ], GL_STREAM_DRAW );

那么,是否有可能使用下标运算符在C中完成类似的事情?如果没有,并且我必须编写一个函数(例如float vec3_value_at( unsigned int i )),那么static inline它在它定义的头文件中是否有意义?

gre*_*det 13

如果所有结构字段都是相同类型,则可以使用union作为以下内容:

typedef union vec3_u
{
    struct vec3_s {
        float x, y, z;
    };
    float vect3_a[3];
}
vec3;
Run Code Online (Sandbox Code Playgroud)

这样,您可以独立访问每个x,y或z字段,或使用vect3_a数组迭代它们.这个解决方案在内存或计算方面没有任何成本,但我们可能与C++类似的解决方案有点远.

  • 未定义的行为?“6.2.6.1.7:当值存储在联合类型对象的成员中时,与该成员不对应但与其他成员对应的对象表示的字节采用未指定的值。” (2认同)

Pau*_*kin 6

您无法获得 C++ 的语法糖,但是很容易将您在 C++ 中编写的函数编写为运算符[]。

float get_vec3(v *vec3, int i) {
   switch(i) {
   case 0: return v->x;
   case 1: return v->y;
   case 2: return v->z;
   }
   assert(0);
 }
Run Code Online (Sandbox Code Playgroud)

现在您可以迭代任何 vec3。

 for (int i = 0; i < 3; i++) {
     printf("%f\n", get_vec3(v, i));
 }
Run Code Online (Sandbox Code Playgroud)