从宏调用函数 [英] Calling a function from a macro

查看:168
本文介绍了从宏调用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好我试图创建一个计算C中的数字的数量应该是,它也已经#define如下所示的表的大小的基体2的对数的宏

Hi I am trying to create a macro that computes the base 2 logarithm of a number in C. The number is supposed to be the size of a table that is #defined also as seen below.

我搜索了一圈,发现这个网站包含base2log的实现
https://graphics.stanford.edu/~seander/bithacks.html

I searched around and found this site that contains an implementation of base2log https://graphics.stanford.edu/~seander/bithacks.html

uint8_t base2log(uint16_t value){

    uint8_t result = 0; // r will be lg(v)

    while (value >>= 1)
    {
        result++;
    }
    return result;
}

我的第一个想法是,现在创建宏为:

My first idea is to now create the macro as:

#define SIZE 256
#define BASE2LOG (base2log(SIZE))

...但是这看起来并不像一个很优雅的解决方案,因为即使BASE2LOG应该在编译的时候定义它仍然需要调用一个函数每次这个出现在code。我想也许在一个全局变量赋值BASE2LOG,但我相信一定有什么比这更简洁和适当的。

...but this doesn't look like a very elegant solution, because even though BASE2LOG should be defined at compile time it will still need to call a function everytime this appears in the code. I thought of perhaps assigning BASE2LOG in a global variable but I am sure that there must be something more concise and proper than this.

有没有办法做到这一点?

Is there a way to do this?

感谢您的时间。

推荐答案

下面是一个纯粹的宏观解决方案,允许对数在编译时计算并用在一个的整型常量前pression 的预计用C - 例如,指定(非可变长度)数组的长度时。的整型常量前pression 的只是standardese的Ex pression的编译器必须能够在编译时评估。

Here's a pure macro solution that allows the logarithm to be computed at compile time and used where an integer constant expression is expected in C -- e.g., when specifying the length of a (non-variable length) array. Integer constant expression is just standardese for an expression the compiler must be able to evaluate at compile time.

我见过的这个变种在其他地方(在<一个有一href=\"http://stackoverflow.com/questions/6834868/macro-to-compute-number-of-bits-needed-to-store-a-number-n\">macro计算存储一个数n 的为例)所需的比特数,所以我不能居功。我可以写了它是如何工作最少。

I've seen variants of this in other places (and there's one in macro to compute number of bits needed to store a number n for example), so I can't take credit. I could write up how it works at least.

// Computes the base 2 logarithm of a 16-bit number. Meant to be used
// at compile time.
#define LOG2(n)   ((n) & 0xFF00 ? 8 + LOG2_8((n) >> 8) : LOG2_8(n))
#define LOG2_8(n) ((n) & 0xF0   ? 4 + LOG2_4((n) >> 4) : LOG2_4(n))
#define LOG2_4(n) ((n) & 0xC    ? 2 + LOG2_2((n) >> 2) : LOG2_2(n))
#define LOG2_2(n) ((n) & 0x2    ? 1 : 0)

若干截短基座2的对数是最高的1位的只是索引(0是至少显著位的索引)。以找到最高1位,一个类型的二进制搜索的都可以使用。

The truncated base 2 logarithm of a number is just the index of the highest 1 bit (with 0 being the index of the least significant bit). To find the highest 1 bit, a type of binary search can be used.

LOG2()(主宏),我们使用(N)及为0xFF00? ... 来测试,如果高字节包含1位。如果确实如此,那么在 N 是8加最高的1位的 n的高字节中的指数<中最高的1位的索引/ code>。如果没有,则最高1位的索引是低字节内的最高的1位的只是索引

In LOG2() (the main macro), we use (n) & 0xFF00 ? ... to test if the high byte contain a 1 bit. If it does, then the index of the highest 1 bit in n is 8 plus the index of the highest 1 bit within the high byte of n. If it doesn't, then the index of the highest 1 bit is just the index of the highest 1 bit within the low byte.

要获得高字节,我们做(N)GT;&GT; 8 。其余的宏只看低字节,所以没有必要掩盖。

To get the high byte, we do (n) >> 8. The remaining macros only look at the low byte, so there's no need to mask.

LOG2_8()宏计算最高的1位的字节中的索引。它采用相同的逻辑如上减半间隔。如果高4比特包含一个1位,则最高1比特的索引为4加上最高的1位的高4位中的索引。否则,它是最高位的低4位中的索引。

The LOG2_8() macro computes the index of the highest 1 bit within a byte. It uses the same logic as above with a halved interval. If the high 4 bits contain a 1 bit, then the index of the highest 1 bit is 4 plus the index of the highest 1 bit within the high 4 bits. Otherwise, it's the index of the highest bit within the low 4 bits.

LOG_4()的工作方式完全相同。

LOG_4() works exactly the same way.

有关基本情况, LOG2_2(1)== 0 LOG2_2(2)== 1 LOG2_2(0)(这在数学上是不确定的)情况变得过于0

For the base case, LOG2_2(1) == 0 and LOG2_2(2) == 1. LOG2_2(0) (which is mathematically undefined) happens to become 0 too.

宏可以概括在明显的方式来处理更大的类型。比该类型的宽度大的值移位严格不确定的(不知道这是在全国的编译器的做法多么可靠)和需要被关注了。一种方法使之安全是添加石膏(假定C99 +):

The macro can be generalized to handle larger types in the obvious way. Shifting by a value larger than the width of the type is strictly undefined (not sure how reliable it is in practice across compilers) and needs to be watched out for. One way to make it safe would be to add a cast (this assumes C99+):

#define LOG2(n)    LOG2_64((uint64_t)(n))
#define LOG2_64(n) ... /* as usual. */
...

更简单(略spammier)解决方案也是可能的,例如

More straightforward (and slightly spammier) solutions are possible too, e.g.

#define LOG2(n)   \
  ((n) < 2  ? 0 : \
   (n) < 4  ? 1 : \
   (n) < 8  ? 2 : \
   (n) < 16 ? 3 : \
   (n) < 32 ? 4 : \
   (n) < 64 ? 5 : \
   ...

(C99具有 // 的方式风格的注释,万一有人觉得像在抱怨。)

(C99 has //-style comments by the way, in case someone felt like complaining. ;)

这篇关于从宏调用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆