开发者

Evaluate macro parameter once only

In the following code, whatever is passed as retval is evaluated as given for every use of that token.

#define _CPFS_RETURN(commit, retval) do { \
        util_cpfs_exit(commit); \
        return retval; \
    } while (false)

#define CPFS_RETURN_BOOL(retval) do { \
        _CPFS_RETURN(retval, retval); \
    } while (false)

For example given the use CPFS_RETURN_BOOL(inode && file_truncate(inode, len));, this is generated:

do { 
    do {
        util_cpfs_exit(inode && file_truncate(inode, len));
        return inode && file_truncate(inode, len);
    } while (0);
} while (0);

Evidently I don't want to execute the statement inode && file_truncate(inode, len); more than once. How can I ensure that the given tokens are evaluated before being pasted helter-skelter?

Update

I believe I have good reason to use macros here. Where possible, c开发者_运维百科ode is put into real functions (such as util_cpfs_exit) which are invoked from a set of macros I'm using. The macros vary based on the return type: in C++ I'd have explicit templates to handle this.


As your macro vary on the return type, you can evaluate the retval expression and store it in a variable of the right type inside the first level of macro then use this variable. ie:

#define CPFS_RETURN_BOOL(retval) do { \
    bool _tmp_ = retval;
    _CPFS_RETURN(_tmp_, _tmp_); \
} while (false);

If I understand well, that should be enough for your use case, and for other use cases you can use functions.

In your exemple you'll get:

do {
   bool _tmp_ = inode && file_truncate(inode, len);
   do {
      util_cpfs_exit(_tmp_);
      return _tmp_;
   } while (0);
} while (0);

Looks fine.

PS: as a sidenote if you always use _CPFS_RETURN indirectly through another macro following the above model, there is no need to protect it by a do { } while (false);. Also, putting a semi-colon after the while(false) removes most of the interest of using it... that may be a good example of why C macros are dangerous and hides easy pitfalls. Not that I dislike macros, quite the contrary. I'm from the (probably rare) kind of people that would prefer C macros to be enhanced to bypass their current limitations to become really cool (and no, C++ templates are not enhanced macros, they are something completely different).


I would recommend that you evaluate the condition first.

i.e.

bool val = inode && file_truncate(inode, len);

Other than that may advice would be to steer well clear of macros, they seem unnecessary in this instance, use functions instead.


Write a function instead of using a macro. In this case, where you want to build a return statement in, you might be better off just writing the code explicitly instead of relying on a macro to hide what you're doing.


Change the macro to a "static inline" function. In gcc, it's as fast as a macro. http://gcc.gnu.org/onlinedocs/gcc/Inline.html

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜