Abhishek Ravi
Abhishek Ravi

Reputation: 137

C macro to return a Struct

Is there a way to have a macro do exactly what this function does? I'm fairly new to C, any help is appreciated!

vector vectorScale(float c, vector *v){
    vector result = {v->x * c, v->y * c, v->z * c };
    return result;
}
typedef struct{
    float x,y,z;
}vector;

I'm currently trying this but getting errors:

#define vectorScale(vector v, vector c)    vector {float (v->x * c); float (v->y * c); float (v->z * c); }

Upvotes: 5

Views: 2080

Answers (2)

Eric Postpischil
Eric Postpischil

Reputation: 222753

#define vectorScale(c, v) \
    ((vector) {(v)->x * (c), (v)->y * (c), (v)->z * (c) })

This construct, of the form (type) { initial values }, is called a compound literal. It is an object of the type type.

However, with a decent compiler, it should serve to use a static inline function:

static inline vector vectorScale(float c, vector *v)
{
    return (vector) {v->x * c, v->y * c, v->z * c };
}

A good compiler should optimize this to be as efficient as the macro, and it avoids issues with v or c being expressions with side effects.

Upvotes: 6

Jean-François Fabre
Jean-François Fabre

Reputation: 140188

macros arguments don't have a type. You want:

#define vectorSub(c,v) {(v)->x * (c), (v)->y * (c), (v)->z * (c) } 

That's the best equivalent unless someone calls your macro like this:

vector v2 = vectorSub(i++,v);

which is the common issue with macros using their parameters more than once because it will expand as:

{(v)->x * (i++), (v)->y * (i++), (v)->z * (i++) }

Complete self-contained and compiling example:

typedef struct  {
  float x,y,z;
} vector;

#define vectorSub(c,v) {(v)->x * (c), (v)->y * (c), (v)->z * (c) } 

vector foo()
{
  vector v = {0,3,4};
  vector v2 = vectorSub(12,&v);
  return v2;
}

note that a good compiler can/will inline such short functions, as your original vectorScale, specially if the inline keyword is used to send a hint the compiler (compiler doesn't necessarily comply) and the function is in the header file, so macros aren't the best choice here, specially since they don't involve macro trickery like token-pasting or stringing.

Upvotes: 5

Related Questions