在GCC中内嵌了两个位运算的函数,但在VC中并没有这两个函数(有相似函数)。

//返回前导的0的个数。
int __builtin_clz (unsigned int x)
//返回后面的0个个数,和__builtin_clz相对。
int __builtin_ctz (unsigned int x)

这两个函数在radix tree中直接计算索引,对性能有一定要求。

自己写有些效率问题不是很理想,所以想确定vc2015 版本中是否有带已经优化过的函数。

在网上兜了一圈,没有找到类似VC实现的代码。折腾了半天没找到解决方案,后来到CSDN上发了个贴解决问题。

VC相似函数

_BitScanForward()
[ref]: https://msdn.microsoft.com/en-us/library/wfd9z0bb.aspx _BitScanReverse()
[ref]: https://msdn.microsoft.com/en-us/library/fbxyd7zd.aspx

有64位版本的处理,需要处理一下就和GCC中得到相同结果


基本原理

  • 正向扫描指令BSF(BitScan Forward)从右向左扫描,即:从低位向高位扫描;
  • 逆向扫描指令BSR(BitScan Reverse)从左向右扫描,即:从高位向低位扫描。

处理方法

下面简单实现这两个函数。把这两个测试代码贴出来供遇到同样问题的人提帮助。

输出的值和GCC版本是一致的,可直接使用。

vc test code(32位)

// ConsoleApplication1.cpp : Defines the entry point for the console application.
// #include "stdafx.h"
#include <bitset> using namespace std; __inline int __builtin_clz(int v)
{
if (v == 0)
return 31; __asm
{
bsr ecx, dword ptr[v];
mov eax, 1Fh;
sub eax, ecx;
}
} __inline int __builtin_ctz(int v)
{
int pos;
if (v == 0)
return 0; __asm
{
bsf eax, dword ptr[v];
}
} int main()
{
// clz
printf("__builtin_clz:\n");
for (int i = 0; i < 32; i++) {
int v = 1 << i;
bitset<32> b(v);
printf("%12u(%s): %2d %s \n", v, b.to_string().c_str(), __builtin_clz(v), __builtin_clz(v) == 31 - i ? "OK" : "Err");
}
printf("\n"); // ctz
printf("__builtin_ctz:\n");
for (int i = 0; i < 32; i++) {
int v = 1 << i;
bitset<32> b(v);
printf("%12u(%s): %2d %s \n", v, b.to_string().c_str(), __builtin_ctz(v), __builtin_ctz(v) == i ? "OK" : "Err");
} return 0;
}

感谢CSND论坛的zwfgdlc提供帮助

VC中实现GCC的2个比较常用的位运算函数的更多相关文章

  1. 剑指offer-面试题56_1-数组中只出现一次的两个数字-位运算

    /* 题目: 求数组A中只出现一次的数字,该数组中有2个数字a.b仅出现一次,其余均出现两次 */ /* 思路: 两个相同的数字异或为0. 遍历数组,得到数组中各数字异或后的结果x,结果x=a^b. ...

  2. 状态压缩中常用的位运算(DP)

    面对位运算,一直很无感...可能数学太差,脑洞太小. 1.首先是最基本的: 与&,或|,非~,异或^. 2.获取一个或者多个固定位的值: 假设 x = 1010(二进制),我们要取左数第二位的 ...

  3. C语言中的位运算的技巧

    一.位运算实例 1.用一个表达式,判断一个数X是否是2的N次方(2,4,8,16.....),不可用循环语句. X:2,4,8,16转化成二进制是10,100,1000,10000.如果减1则变成01 ...

  4. C#枚举中的位运算权限分配

    什么是位运算 常用的位运算主要有与(&), 或(|)和非(~), 比如: & = ; | = ; ~ = ; 运用在权限设计中 先建立一个枚举表示所有的权限管理操作: [Flags] ...

  5. 旧文备份:VC中嵌入NASM编写的汇编函数

    在公司开发的RT下没法使用C库,并且替代库函数没有几个,需要用到setjmp和longjmp函数,没办法,只能自己想办法了,上sourceforge淘换到一个小日本的工程,提供这两个函数的替代源码,名 ...

  6. VC++中StretchBlt图像失真问题的解决办法

    在 VC 中使用 StretchBlt 会碰到一些与点阵图大小缩放相关的一些问题.在扩展一个点阵图时,StretchBlt必须复制图素行或列.如果放大倍数不是原图的整数倍,那么此操作会造成产生的图像有 ...

  7. VC++中开发汇编语言(转)

    汇编程序结构 一个显示字符串的汇编程序 程序格式 一.模式定义 二.includelib语句 三.函数声明语句 四.数据和代码部分 Visual C/C++环境 建立工程 汇编程序的调试 一.设置断点 ...

  8. VC中实现文字竖排的简单方法

    好多人都觉得在VC中实现文字竖排是一件很难的事情,其实可以使用“躺”着的字体很方便的实现文字竖排. Windows中有一些字体是“躺”着的,例如:@Fixedsys.@System.@宋体.@黑体等等 ...

  9. VC中基于 Windows 的精确定时[转]

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

随机推荐

  1. Flex 日期选择器控件

    在构建用户界面时,经常用到日期的输入和选择. 输入日期时,用户可以使用键盘输入,也可以在类似于日历的弹出式对话框中,通过鼠标单击所选日期. 在Flex中可以通过日期输入控件实现输入和选择日期.Flex ...

  2. Crystal Report 处理当前系统时间

    Changed the print date format to HH/yy/MM/mm/SS/dd  (For Example:2014/01/23 16:30:45= 161430014523) ...

  3. size_t 与 int 区别

    size_t是无符号的,并且是平台无关的,表示0-MAXINT的范围, 但是如果传入的是负数,会被编译成他的补码. size_t是标准规定的一个同义词,它的原始定义放在stddef.h里面,不同的环境 ...

  4. mysql 连接命令 表管理 ,克隆表,临时表,字符串属性,设定语句间的分隔符

    连接和断开连接mysql -h host -u user -p (即,连接的主机.用户名和使用的密码).断开输入QUIT (或\q)随时退出: 表管理克隆表注意:create table ... li ...

  5. CRC校验代码实现

    1.CRC校验简介 CRC就是块数据的计算值,它的全称是“Cyclic Redundancy Check”,中文名是“循环冗余码”.CRC校验是数据通讯中最常采用的校验方式.在嵌入式软件开发中,经常要 ...

  6. mjrefresh源码分析

    最近想自己写个下拉刷新的库,但是始终感觉无从下手,想想总是容易的.原理也很简单,真正要下手写的时候,呵呵.不得不说ios封装得很好,网上可以用的成熟的库也很多,也正是因为如此很多开发者也忽略了很多底层 ...

  7. Excel 代码

    package com.chinabase.common.util; import java.io.FileInputStream; import java.io.FileOutputStream; ...

  8. CSS3 圆形时钟式网页进度条

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. C++ 学习基础一

    1.预处理器指示符如果文件名用尖括号“<”和”>”括起来的,则表示该文件是工程或标准头文件,查找过程会检查预定义的目录.如果文件名用双引号括起来,则表示该文件是用户自定义的头文件,查找该文 ...

  10. RAW格式

    一.什么是RAW文件?RAW文件主要是一种记录了数码相机传感器的原始信息,同时伴随着一些由相机所产生的一些元数据(metadata,诸如IS0的设置.快门速度.光圈值.白平衡等)的文件.不同的相机制造 ...