tags:

views:

89

answers:

5

Is len correctly initialized and safe in set_array call?

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), len);
}

If not, what would you recommend?

A: 

You are passing len by value into the object_set_array() call before it is initialized. So that is wrong and a good compiler will warn about that. The variable will contain a random value, so the code will not crash, but it won't do what you probably want.

Peter Eisentraut
+1  A: 

No. The third parameter of object_set_array() might be evaluated and pushed onto the stack before the second parameter (object_get_array()) is evaluated.

Probably you want

void object_copy (Object* self, Object* obj) {
    int len;
    /* I'm just guessing as to the return type */
    Object *pObj = object_get_array(obj, &len); 
    object_set_array (self, pObj, len);
}
egrunin
@sth: yeah, I knew I was skirting the calling-convention issue, thanks.
egrunin
+6  A: 

No - there's no defined order of evaluation for arguments to a function call.

Even though the call to object_get_array() has to occur before the call to object_set_array(), the value that the compiler calculates and passes to object_set_array() for the len parameter can be done before the compiler makes the call to object_get_array().

I'm not sure what the 2nd parameter to the object_set_array() call is intended to be - maybe you wanted to use the comma operator:

void object_foo (Object* self, Object* obj) {
    int len;

    object_set_array (self, (object_get_array (obj, &len), len));
}

Which would work, but is confusing and something I wouldn't recommend.

I think what you want is:

void object_foo (Object* self, Object* obj) {
    int len;

    object_get_array (obj, &len);  // get the length from obj

    object_set_array (self, len)); // set the len for self
}
Michael Burr
Second one is more readable too.
GMan
A: 
tommieb75
A: 

This will also work:

ARRAY object_get_array (Object* self, int* len);
void object_set_array (Object* self, ARRAY array, const int* len);

// ...

void object_copy (Object* self, Object* obj) {
    int len;
    object_set_array (self, object_get_array (obj, &len), &len);
}

because the call to object_get_array() will always be evaluated before the call to object_set_array(), at which point len will have been set to the correct value.

finnw
that was the object of my question, and it looks like other answers are clear about evaluation order being undefined in C for arguments. Can you provide more information to confirm your answer?
elmarco
The point is that `len` is passed by reference after it is assigned, rather than by value (possibly before it is assigned.)
finnw