[英]Sign extension from 16 to 32 bits in C
我必須為 16 位 integer 進行符號擴展,由於某種原因,它似乎無法正常工作。 誰能告訴我代碼中的錯誤在哪里? 我已經為此工作了好幾個小時。
int signExtension(int instr) {
int value = (0x0000FFFF & instr);
int mask = 0x00008000;
int sign = (mask & instr) >> 15;
if (sign == 1)
value += 0xFFFF0000;
return value;
}
指令(instr)是 32 位,在它里面我有一個 16 位的數字。
為什么會出錯:
int16_t s = -890;
int32_t i = s; //this does the job, doesn't it?
使用內置類型有什么問題?
int32_t signExtension(int32_t instr) {
int16_t value = (int16_t)instr;
return (int32_t)value;
}
或者更好(如果通過int32_t
可能會產生警告)
int32_t signExtension(int16_t instr) {
return (int32_t)instr;
}
或者,對於所有重要的事情,將signExtension(value)
替換為((int32_t)(int16_t)value)
您顯然需要為int16_t
和int32_t
數據類型包含<stdint.h>
。
只是在尋找其他東西時遇到了這個問題,可能有點晚了,但也許它對其他人有用。 AFAIAC 所有 C 程序員都應該開始編程匯編程序。
無論如何,擴展符號比提案要容易得多。 只需確保您使用有符號變量,然后使用 2 個班次即可。
long value; // 32 bit storage
value=0xffff; // 16 bit 2's complement -1, value is now 0x0000ffff
value = ((value << 16) >> 16); // value is now 0xffffffff
如果變量有符號,則 C 編譯器將 >> 轉換為保留符號的算術右移。 此行為與平台無關。
因此,假設值以 0x1ff 開頭,那么我們有,<< 16 將 SL(左移)該值,因此 instr 現在是 0xff80,然后 >> 16 將 ASR 值因此 instr 現在是 0xffff。
如果您真的想玩宏,請嘗試這樣的事情(GCC 中的語法在 MSVC 中沒有嘗試過)。
#include <stdio.h>
#define INT8 signed char
#define INT16 signed short
#define INT32 signed long
#define INT64 signed long long
#define SIGN_EXTEND(to, from, value) ((INT##to)((INT##to)(((INT##to)value) << (to - from)) >> (to - from)))
int main(int argc, char *argv[], char *envp[])
{
INT16 value16 = 0x10f;
INT32 value32 = 0x10f;
printf("SIGN_EXTEND(8,3,6)=%i\n", SIGN_EXTEND(8,3,6));
printf("LITERAL SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,0x10f));
printf("16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value16));
printf("32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=%i\n", SIGN_EXTEND(16,9,value32));
return 0;
}
這將產生以下 output:
SIGN_EXTEND(8,3,6)=-2
LITERAL SIGN_EXTEND(16,9,0x10f)=-241
16 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241
32 BIT VARIABLE SIGN_EXTEND(16,9,0x10f)=-241
嘗試:
int signExtension(int instr) {
int value = (0x0000FFFF & instr);
int mask = 0x00008000;
if (mask & instr) {
value += 0xFFFF0000;
}
return value;
}
人們指出鑄造和左移,然后是算術右移。 另一種不需要分支的方式:
(0xffff & n ^ 0x8000) - 0x8000
如果高 16 位已經為零:
(n ^ 0x8000) - 0x8000
• 社區維基,因為它是“聚合魔法算法,符號擴展”中的一個想法
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.