什么是std :: __ lg?

时间:2016-11-05 04:09:54

标签: c++ std

作为标题我不知道谷歌之后的std::__lg是什么意思吗?这条线到底是做什么的:int n = std::__lg(block_sz - pos_l + 1);

2 个答案:

答案 0 :(得分:3)

帮助计算整数的2对数,即返回数字中最高设置位的索引(或-1表示0)。

即。对于1,它将返回0,对于16,它将返回4,对于1024,它将返回10,等等。

这可以用来有效地预测数组的预分配大小,舍入到最接近2的幂等等。

注意,作为以__开头的任何其他函数,它是编译器或库的内部函数,所以你不应该依赖它的存在,这样的代码不可移植。 std库的其他实现可以带有完全解决方案和类似帮助程序的不同名称(如果它们使用类似的东西)。

POSIX提供了类似的功能 - ffs(),还有ffsl和ffsll(参见同一页面),这是GNU扩展,分别使用long和long long。

对于评论中的问题 - 如何从Java中使用它。由于上述原因,它首先不是好主意,其次需要JNI包装器。第三,但最重要的是 - 实际上没有理由这样做。 Java已经提供了类似的方法Integer.heghestOneBit(),但是注意它与描述的std :: __ lg相比返回+1,即0代表0,1代表1,11代表1024等等。

答案 1 :(得分:2)

它是编译器内部使用的标识符(非常可能是GCC),因为所有带有双下划线的标识符都属于编译器实现。

在您自己的代码中没有任何地方可以看到或使用__lg之类的内容。使用标准库的接口,而不是其实现。如果您自己的代码直接使用__lg,那么您无法保证代码可以编译或使用任何其他编译器或甚至任何其他版本的相同编译器执行正确的操作。< / p>

正如C ++标准所述,§2.10[lex.name]

  

包含双下划线 __或开始的每个标识符   下划线后跟一个大写字母保留给   实施任何用途。

至于GCC的实际情况,只需查看Google搜索“std :: __ lg”的source code

根据block_szpos_l的实际类型,它应该是:

/// This is a helper function for the sort routines and for random.tcc.
//  Precondition: __n > 0.
template<typename _Size>
  inline _Size
  __lg(_Size __n)
  {
    _Size __k;
    for (__k = 0; __n != 0; __n >>= 1)
  ++__k;
    return __k - 1;
  }

或者这个:

inline int
__lg(int __n)
{ return sizeof(int) * __CHAR_BIT__  - 1 - __builtin_clz(__n); }

现在,__CHAR_BIT__就像标准的CHAR_BIT宏一样。正如GCC documentation所说:

  

定义为char表示中使用的位数   数据类型。存在使标准标题给出数字   限制工作正常。你不应该直接使用这个宏;   相反,请包含相应的标题。

__builtin_clz是另一个GCC特定的功能。同样,GCC documentation解释了其目的:

  

从最开始返回x中前导0位的数量   重要的位置。如果x为0,则结果未定义。

我认为如果你需要这样的功能,那么自己编写它是微不足道的。事实上,问题是为什么你首先需要它。您实际问题的真正答案可能在于int n = std::__lg(block_sz - pos_l + 1);行周围的代码。

要记住的事情:

  • 请勿在自己的代码中使用带有两个连续下划线的任何内容。
  • GCC是开源的,因此特殊功能或宏的内部实现并不是秘密,但可以很容易地在线浏览。