![](/img/trans.png)
[英]Unexpected sign extension of int32 or 32bit pointer when converted to uint64
[英]Determine the sign of a 32 bit int
僅使用:
! 〜&^ | + << >>
沒有LOOPS
我需要確定32位整數的符號,如果為正則需要返回1,如果為0則返回0,如果為負則返回-1。
有任何想法嗎? 我首先考慮轉移31位,然后看着那個標志,但顯然不會工作,現在我有點卡住了。
試試這個:
(x >> 31) | (((0 - x) >> 31) & 1)
這個怎么樣:
(x >> 31) | (((~x + 1) >> 31) & 1)
編輯2:
回應評論中提出的問題(或者說是挑選)
這些解決方案的假設是有效的:
0
與x的類型相同。 如果條件表達式(不if
語句)和減法是允許的,最簡單和清晰的解決方案(IMO)是:
int sign = (v > 0) - (v < 0);
不使用減法(假設int
是32位):
#include <stdio.h>
#include <assert.h>
#include <limits.h>
int process(int v) {
int is_negative = (unsigned int)v >> 31; // or sizeof(int) * CHAR_BIT - 1
int is_zero = !v;
int is_positive = !is_negative & !is_zero;
int sign = (is_positive + ~is_negative) + 1;
return sign;
}
int main() {
assert(process(0) == 0);
printf("passed the zero test\n");
for (int v = INT_MIN; v < 0; v++) {
assert(process(v) == -1);
}
printf("passed all negative tests\n");
for (int v = 1; v < INT_MAX; v++) {
assert(process(v) == +1);
}
printf("passed all positive tests\n");
return 0;
}
結果如下:
$ gcc -o test test.c -Wall -Wextra -O3 -std=c99 && ./test && echo $#
passed zero test
passed all negative tests
passed all positive tests
0
為什么需要使用按位運算符?
int get_sign(int value)
{
return (value < 0) ? -1 : (int)(value != 0);
}
如果您必須使用按位運算符,則可以使用&
運算符檢查負值,無需轉換:
int get_sign(int value)
{
return (value & 0x80000000) ? -1 : (int)(value != 0);
}
如果你想轉移:
int get_sign(int value)
{
return ((value >> 31) & 1) ? -1 : (int)(value != 0);
}
有點復雜,但有這樣的:
(~((x >> 31) & 1) + 1) | (((~x + 1) >> 31) & 1)
這應該考慮到班次是填寫1還是0的模糊性
對於細分,我們有這個構造的任何地方:
(z >> 31) & 1
當否定時將導致1,否則將導致0。
我們有的地方:
(~z + 1)
我們得到否定的數字(-z)
因此,如果x為負,則前半部分將產生0xFFFFFFFF(-1)的結果,如果x為正,則后半部分將產生0x00000001(1)。 如果兩者都不為真,則按位或將它們組合在一起將產生0x00000000(0)。
我不確定這是絕對理想的做事方式,但我認為這是合理的便攜性,至少比你的方式簡單:
#define INT_BITS 32
int sign(int v) {
return (!!v) | -(int)((unsigned int)v >> (INT_BITS-1));
}
關於什么:
int getsign(int n)
{
return (!!n) + (~((n >> 30) & 2) + 1);
}
..對於32位signed int,僅限2的補碼。
!!n
如果n
非零,則!!n
給出1。 ((n >> 30) & 2)
如果設置了高位(符號)則給出2。 按位NOT和+1取2的補碼,給出-2或0.對於負值,加法給出-1(1 + -2),對於零,給出0(0 + 0),+1(1 + 0)為正值。
假設實現定義了算術右移:
(x>>31) | !!x
與Mystical的答案不同,沒有UB。
並且,如果您還想支持將右移定義為算術移位的系統:
~!(x>>31)+1 | !!x
編輯:對不起,我省略了!
在第二個版本。 它應該是:
~!!(x>>31)+1 | !!x
這個版本仍然是依賴於實現是二進制補碼和具有或者算術或邏輯右移,即如果實現定義的行為是別的東西完全可能打破。 但是,如果將類型更改為無符號類型,則所有實現定義的行為都將消失,結果為-1U
, 0U
或1U
具體取決於x
的“符號”(高位和零/非零狀態)。
迪米特里的想法可以簡化為(!! x) - ((x >> 30)&2)
而且只是提出一個更神秘的解決方案:
~!x & ((-((unsigned) x >> 31)) | !!x)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.