C语言 C 语言中从 16 位到 32 位的符号扩展
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6215256/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sign extension from 16 to 32 bits in C
提问by Sorin Cioban
I have to do a sign extension for a 16-bit integer and for some reason, it seems not to be working properly. Could anyone please tell me where the bug is in the code? I've been working on it for hours.
我必须对 16 位整数进行符号扩展,但出于某种原因,它似乎无法正常工作。谁能告诉我代码中的错误在哪里?我已经为此工作了几个小时。
int signExtension(int instr) {
int value = (0x0000FFFF & instr);
int mask = 0x00008000;
int sign = (mask & instr) >> 15;
if (sign == 1)
value += 0xFFFF0000;
return value;
}
The instruction (instr) is 32 bits and inside it I have a 16bit number.
指令 (instr) 是 32 位,在它里面我有一个 16 位的数字。
采纳答案by qbert220
Try:
尝试:
int signExtension(int instr) {
int value = (0x0000FFFF & instr);
int mask = 0x00008000;
if (mask & instr) {
value += 0xFFFF0000;
}
return value;
}
回答by Nawaz
Why is wrong with:
为什么会出错:
int16_t s = -890;
int32_t i = s; //this does the job, doesn't it?
回答by CAFxX
what's wrong in using the builtin types?
使用内置类型有什么问题?
int32_t signExtension(int32_t instr) {
int16_t value = (int16_t)instr;
return (int32_t)value;
}
or better yet (this might generate a warning if passed a int32_t)
或者更好(如果传递 a ,这可能会产生警告int32_t)
int32_t signExtension(int16_t instr) {
return (int32_t)instr;
}
or, for all that matters, replace signExtension(value)with ((int32_t)(int16_t)value)
或者,对于所有重要的事情,替换signExtension(value)为((int32_t)(int16_t)value)
you obviously need to include <stdint.h>for the int16_tand int32_tdata types.
你显然需要包括<stdint.h>用于int16_t和int32_t数据类型。
回答by SurrealWombat
Just bumped into this looking for something else, maybe a bit late, but maybe it'll be useful for someone else. AFAIAC all C programmers should start off programming assembler.
刚刚碰到这个寻找其他东西,也许有点晚了,但也许它对其他人有用。AFAIAC 所有 C 程序员都应该从汇编程序开始。
Anyway sign extending is much easier than the proposals. Just make sure you are using signed variables and then use 2 shifts.
无论如何,标志扩展比提案容易得多。只要确保您使用的是带符号的变量,然后使用 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
If the variable is signed then the C compiler translates >> to Arithmetic Shift Right which preserves sign. This behaviour is platform independent.
如果变量是有符号的,那么 C 编译器会将 >> 转换为算术右移,从而保留符号。此行为与平台无关。
So, assuming that value starts of with 0x1ff then we have, << 16 will SL (Shift Left) the value so instr is now 0xff80, then >> 16 will ASR the value so instr is now 0xffff.
因此,假设值从 0x1ff 开始,那么我们有,<<16 将 SL(左移)值,因此 instr 现在是 0xff80,然后 >> 16 将 ASR 值,因此 instr 现在是 0xffff。
If you really want to have fun with macros then try something like this (syntax works in GCC haven't tried in MSVC).
如果你真的想玩弄宏,那么试试这样的东西(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;
}
This produces the following 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
回答by Chai T. Rex
People pointed out casting and a left shift followed by an arithmetic right shift. Another way that requires no branching:
人们指出转换和左移,然后是算术右移。另一种不需要分支的方法:
(0xffff & n ^ 0x8000) - 0x8000
If the upper 16 bits are already zeroes:
如果高 16 位已经为零:
(n ^ 0x8000) - 0x8000
? Community wiki as it's an idea from "The Aggregate Magic Algorithms, Sign Extension"
? 社区维基,因为它是“聚合魔法算法,符号扩展”的一个想法

