签名hex字符串到long int函数

我需要一个函数将32位或24位带符号(二进制补码)hex字符串转换为long int。 需要在32位和64位机器上工作(无论长度大小如何),无论机器是否是双补机,都需要工作。

解:

long int hex2li (char hexStr[], int signedHex) { int bits = strlen (hexStr) * 4; char *pEnd; long long int result = strtoll (hexStr, &pEnd, 16); if (pEnd[0] == '\0') { if (signedHex) { if (result >= (1LL << (bits - 1))) result -= (1LL << bits); } return (long int) result; } return LONG_MIN; } 

对于24位字符串:

解析hex字符串时,标准的strtol函数会将其读取为0 -> 2^24 - 1范围内的无符号值。

范围0 -> 2^23 - 1是正确的,但是范围2^23 -> 2^24 - 1需要映射到-2^23 -> -1这是一个简单的减法,可以按如下方式执行。

 if (result >= (1L << 23)) result -= (1L << 24); 

要使用相同的技术转换32位字符串,必须使用中间类型,该中间类型可以表示带符号类型的完整32位无符号整数,以执行减法。 long long int保证为64位,因此您可以使用它。

例如

 long int ParseHexStr(const char *in, int bits) { char* endptr; long long int result; result = strtoll(in, &endptr, 16); /* ** TODO - error checking, eg check endptr != in ** Also check for range errors, signalled by LLONG_MIN ** LLONG_MAX and a errno == ERANGE. */ if (result >= (1LL << (bits - 1)) result -= (1LL << bits); return result; } 

我们有一个SIGN_EXTEND宏,看起来像:

 #define SIGN_EXTEND(X, SignBit, Type) \ (((Type) ((X) << (8 * sizeof(Type) - (SignBit) - 1))) >> \ (8 * sizeof(Type) - (SignBit) - 1)) 

当符号位置位时,它依赖于>>运算符1 – 填充输入。 使用它像:

 SIGN_EXTEND(0x89abcd, 23, int32_t); 

对于您的问题,您可以使用:

 long int hex2li (char string[]) { char *pEnd; long int result = SIGN_EXTEND(strtol (string, &pEnd, 16), 23, long int); if(pEnd[0] == '\0') return result; return LONG_MIN; } 

这种比较是错误的: if (toupper (string[0]) == 'F')

您需要使用MSB集对任何值进行符号扩展,例如:

if(strchr("89ABCDEF", toupper(string[0])) != NULL)

有没有理由不能将strtol与16号基数一起使用?

  if (toupper (string[0]) == 'F') { return (result | 0xFF000000); } 

这将生成带有正确符号的数字。

  if (toupper (string[0]) == 'F') { return ( ~(result | 0xFF000000) + 1); } 

这将永远产生积极的结果