ph7*_*ph7 2 c int char negative-number
如何获取整数的符号并将其存储在char中?一种方法是:
int n = -5
char c;
if(n<0)
c = '-';
else
c = '+';
Run Code Online (Sandbox Code Playgroud)
要么:
char c = n < 0 ? '-' : '+';
Run Code Online (Sandbox Code Playgroud)
但是有没有条件的方法吗?
这会在x86-64上使用gcc / clang创建无分支的代码:
void storeneg(int X, char *C)
{
*C='+';
*C += (X<0)*('-'-'+');
}
Run Code Online (Sandbox Code Playgroud)
https://gcc.godbolt.org/z/yua1go
有一种最高效,最便携式的方法,但是它并没有赢得任何美容大奖。
我们可以假设有符号整数的MSB始终为负。即使考虑到异国签名格式(一个补码,一个符号大小),这也是100%可移植的假设。因此,最快的方法是简单地从整数中屏蔽掉MSB。
在位置可以找到任何整数的MSB CHAR_BIT * sizeof(n) - 1;。在典型的32位主流系统上,该值例如为8 * 4 - 1= 31。
因此,我们可以编写如下函数:
_Bool is_signed (int n)
{
const unsigned int sign_bit_n = CHAR_BIT * sizeof(n) - 1;
return (_Bool) ((unsigned int)n >> sign_bit_n);
}
Run Code Online (Sandbox Code Playgroud)
在x86-64 gcc 9.1(-O3)上,这会产生非常有效的代码:
is_signed:
mov eax, edi
shr eax, 31
ret
Run Code Online (Sandbox Code Playgroud)
此方法的优点还在于,与诸如之类的代码不同x < 0,在移植时,它不会冒被翻译成“如果否定分支”指令的风险。
完整的例子:
#include <limits.h>
#include <stdio.h>
_Bool is_signed (int n)
{
const unsigned int sign_bit_n = CHAR_BIT * sizeof(n) - 1;
return (_Bool) ((unsigned int)n >> sign_bit_n);
}
int main (void)
{
int n = -1;
const char SIGNS[] = {' ', '-'};
char sign = SIGNS[is_signed(n)];
putchar(sign);
}
Run Code Online (Sandbox Code Playgroud)
拆卸(x86-64 gcc 9.1(-O3)):
is_signed:
mov eax, edi
shr eax, 31
ret
main:
sub rsp, 8
mov rsi, QWORD PTR stdout[rip]
mov edi, 45
call _IO_putc
xor eax, eax
add rsp, 8
ret
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
84 次 |
| 最近记录: |