23 c performance hex strtol
在C语言中,什么是十六进制数字字符串转换成二进制最有效的方法unsigned int还是unsigned long?
例如,如果我有0xFFFFFFFE,我想要一个intbase10值4294967294.
Orw*_*ile 31
编辑:现在与MSVC,C++和非GNU编译器兼容(参见结束).
问题是"最有效的方式".OP没有指定平台,他可能正在编译基于RISC的ATMEL芯片,其代码具有256字节的闪存存储器.
为了记录,以及那些(像我一样),欣赏"最简单的方法"和"最有效的方式"之间的区别,以及喜欢学习的人...
static const long hextable[] = {
[0 ... 255] = -1, // bit aligned access into this table is considerably
['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // faster for most modern processors,
['A'] = 10, 11, 12, 13, 14, 15, // for the space conscious, reduce to
['a'] = 10, 11, 12, 13, 14, 15 // signed char.
};
/**
* @brief convert a hexidecimal string to a signed long
* will not produce or process negative numbers except
* to signal error.
*
* @param hex without decoration, case insensitive.
*
* @return -1 on error, or result (max (sizeof(long)*8)-1 bits)
*/
long hexdec(unsigned const char *hex) {
long ret = 0;
while (*hex && ret >= 0) {
ret = (ret << 4) | hextable[*hex++];
}
return ret;
}
Run Code Online (Sandbox Code Playgroud)
它不需要外部库,而且应该非常快.它处理大写,小写,无效字符,奇数大小的十六进制输入(例如:0xfff),最大大小仅受编译器限制.
对于不接受花式hextable声明的非GCC或C++编译器或编译器.
用这个(更长,但更符合)版本替换第一个语句:
static const long hextable[] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
Run Code Online (Sandbox Code Playgroud)
Mar*_*son 16
试试这个:
#include <stdio.h>
int main()
{
char s[] = "fffffffe";
int x;
sscanf(s, "%x", &x);
printf("%u\n", x);
}
Run Code Online (Sandbox Code Playgroud)
小智 8
如果你没有stdlib,那么你必须手动完成.
unsigned long hex2int(char *a, unsigned int len)
{
int i;
unsigned long val = 0;
for(i=0;i<len;i++)
if(a[i] <= 57)
val += (a[i]-48)*(1<<(4*(len-1-i)));
else
val += (a[i]-55)*(1<<(4*(len-1-i)));
return val;
}
Run Code Online (Sandbox Code Playgroud)
注意:此代码假定为大写AF.如果len超出最长的整数32或64位,并且非法十六进制字符没有错误捕获,则它不起作用.
对于AVR微控制器,我编写了以下功能,包括相关注释以使其易于理解:
/**
* hex2int
* take a hex string and convert it to a 32bit number (max 8 hex digits)
*/
uint32_t hex2int(char *hex) {
uint32_t val = 0;
while (*hex) {
// get current character then increment
char byte = *hex++;
// transform hex character to the 4bit equivalent number, using the ascii table indexes
if (byte >= '0' && byte <= '9') byte = byte - '0';
else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;
// shift 4 to make space for new digit, and add the 4 bits of the new digit
val = (val << 4) | (byte & 0xF);
}
return val;
}
Run Code Online (Sandbox Code Playgroud)
例:
char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);
Run Code Online (Sandbox Code Playgroud)
好像经常发生一样,您的问题存在严重的术语错误/歧义。在普通的演讲中,它通常无关紧要,但在这个特定问题的背景下,它至关重要。
你看,没有“十六进制值”和“十进制值”(或“十六进制数”和“十进制数”)这样的东西。“十六进制”和“十进制”是值表示的属性。同时,值(或数字)本身没有表示,因此它们不能是“十六进制”或“十进制”。例如,0xF与15在C语法是两个不同的表示的相同数目。
我猜你的问题,它的表述方式,表明你需要将值(即字符串)的 ASCII 十六进制表示转换为值(另一个字符串)的 ASCII 十进制表示。一种方法是使用整数表示作为中间表示:首先,将 ASCII 十六进制表示转换为足够大小的整数(使用strto...group 中的函数,如strtol),然后将整数转换为 ASCII 十进制表示(使用sprintf)。
如果这不是你需要做的,那么你必须澄清你的问题,因为不可能从你的问题的表述方式中弄清楚。