简体   繁体   English

使用宏来进行小型操作,这是一种很好的做法吗?

[英]Using a macro for a small operation, is this good practice?

I have a small piece of code that requires to read 4-bit values bitpacked in a 32-bit integer. 我有一小段代码需要读取以32位整数进行bitpacked的4位值。 Since I need to call this operation several times, even if it's simple, I require max speed on it. 因为我需要多次调用此操作,即使它很简单,我也需要最大速度。 I was pondering about macros and inline functions, thus I made this macro: 我在思考宏和内联函数,因此我制作了这个宏:

#define UI32TO4(x, p) (x >> ((p - 1) *4) & 15)

And I have an inline function that does the same thing. 我有一个内联函数,可以做同样的事情。

static inline Uint8 foo_getval(Uint32 bits, int pos){
    return (bits >> ((pos-1)*4)) & 15;
}

Considering the simplicity of the operation, and that the values are already prepared for this call (so no possibility of calling on the wrong types, or pass values that are too big or that stuff), what would be the best one to use? 考虑到操作的简单性,并且已经为这个调用准备了值(因此不可能调用错误的类型,或者传递太大或那些东西的值),最好使用什么? Or, at least, the most comprehensible for someone else potentially reading/modifying the code later on? 或者,至少,对于其他可能在以后阅读/修改代码的人来说,最容易理解的是?

EDIT! 编辑! Forgot to mention, I am using C99. 忘了提,我正在使用C99。

The function is safer. 功能更安全。 Your assumptions that the values are always "right" only holds while you're developing that code. 您开发该代码时,您的假设值始终是“正确的”。 You can't tell if someone down the line (or yourself when you're tired) won't pass unexpected values. 你不知道是否有人下线(或你累了的时候)不会传递意外的值。

The compiler will do the inlining when it sees it as effective. 当编译器认为它有效时,它将执行内联。 Use type-safe functions whenever you can, use macros only when you have no other practical choice. 尽可能使用类型安全函数,只有在没有其他实际选择时才使用宏。

I would use the inline function because macros can cause unwanted side effects. 我会使用内联函数,因为宏可能会导致不必要的副作用。 Use macros only to save typing if necessary. 如有必要,仅使用宏来保存输入。

If a macro name is the same name as a function name in an other compilation unit you would get strange compilation errors. 如果宏名称与其他编译单元中的函数名称相同,则会出现奇怪的编译错误。 These problems can be hard to find, especially if the macro is expanded elsewhere and no error occurs. 这些问题很难找到,特别是如果宏在其他地方扩展并且没有发生错误。

Additionally a function warns you about parameter types and would not let you give a double for pos. 此外,一个函数会警告您参数类型,并且不允许您为pos提供双精度。 The macro could allow this. 宏可以允许这个。

It's late, and I'm grumpy (and I'll probably delete this post later) but I get tired of hearing the same arguments against macros parroted over and over again (a double redundacy): 已经很晚了,而且我脾气暴躁(我可能会稍后删除这篇文章)但是我厌倦了听到反复鹦鹉学舌的相同论点(双重冗余):

  • Joachim Pileborg (above) states "using a function allows the compiler to do better typechecking". Joachim Pileborg(上图)指出“使用函数允许编译器做更好的类型检查”。 This is often stated , but I don't believe it. 经常被说明 ,但我不相信。 With macros, the compiler already has all the available type information at its fingertips. 使用宏,编译器已经掌握所有可用的类型信息。 Functions simply destroy this. 功能只是破坏了这个。 (And possibly destroy optimization, by pushing registers out to the stack, but that's a side issue.) (并且可能通过将寄存器推送到堆栈来破坏优化,但这是一个副问题。)

  • And frast (above) states "macros can cause unwanted side effects". 而frast(上图)表示“宏可能会导致不必要的副作用”。 True--but so can functions. 是的 - 但功能也是如此 I think the rule is to always use UPPER_CASE for macros which don't have function semantics. 我认为规则是始终对 没有函数语义的宏使用UPPER_CASE This rule has often been broken. 这条规则经常被打破。 But it doesnt apply here: the OP has redundantly used both uppercase and function semantics. 但它不适用于此:OP冗余地使用大写函数语义。

But I would suggest a tiny improvement. 但我会建议一个微小的改进。 The OP has quite correctly placed parentheses around the whole macro, but there should also be parentheses around each argument: OP在整个宏周围放置了正确的括号,但每个参数周围也应该有括号:

   #define UI32TO4(x, p) ((x) >> (((p) - 1) * 4) & 15)

Always enclose your macro args in parentheses, unless you are doing string or token concatenting, etc. 除非您正在进行字符串或标记连接等,否则请始终将宏args括在括号中。

Macros are, of course, dangerous, but so are functions. 宏当然是危险的,但功能也是如此。 (And the less said of STL, the better). STL,越少越好)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM