在 C 中对 int 进行符号扩展

2024-01-21

所以我在获取 int 字段然后对其进行符号扩展时遇到了一些麻烦。我有一个获取 int 字段的方法。

getField(int value, int hi, int lo);

Value 是我从中获取字段的 int,hi 和 lo 是字段的大小。

所以我可以在 getFieldSignExtended(int value, int hi, int lo) 中调用这个 getField 方法,但是如何对其进行符号扩展呢?

e.g. value = 7, hi = 1, lo = 0

getField(7, 1, 0);返回 3,因为二进制 7 是 111,hi 和 lo 取 0 到 1 的字段。

从 getField 返回 3 后,我得到该值等于 0x0003。

到目前为止,我所掌握的内容在积极方面有效,但在消极方面却很混乱。当我说“搞砸”时,我的意思是它根本不起作用。因此,如果我尝试在 -1 上使用它,它会显示为大整数而不是负数。

谢谢你的帮助! :]

编辑:抱歉,我用一个矛盾的陈述让我自己和你们中的一些人感到困惑:P。固定的。


这里的字里行间有大量的阅读内容。然而,如果getField(7, 1, 0)返回 3 并且你需要getFieldSignExtended(15, 2, 0)回来-3 and getFieldSignExtended(3, 2, 0)回来+3,那么这可能就是您所追求的。

其概念是,将原始值的 hi:lo 位中的 n 位字段视为 2 的补码。如果 n 位中的第一位是 1,则您希望将 n 位字段视为负数。如果 3 位字段的第一位是 0,那么您希望将其视为正数。

#include <assert.h>
#include <limits.h>
#include <stdio.h>

extern int getFieldSignExtended(int value, int hi, int lo);

enum { INT_BITS = CHAR_BIT * sizeof(int) };

int getFieldSignExtended(int value, int hi, int lo)
{
    assert(lo >= 0);
    assert(hi > lo);
    assert(hi < INT_BITS - 1);
    int bits = (value >> lo) & ((1 << (hi - lo + 1)) - 1);
    if (bits & (1 << (hi - lo)))
        return(bits | (~0U << (hi - lo)));
    else
        return(bits);
}

这 3 个断言是直截了当的;唯一有争议的是代码拒绝处理位 31。如果您使用 hi = 31 和 lo = 0 调用它,则移位 (hi - lo + 1) 太大并且行为未定义。您还会遇到右移负数的实现定义行为。可以通过采用无符号整数参数而不执行以下操作来解决这些问题&操作如果hi - lo + 1 == INT_BITS。解决这些问题留给读者作为练习。

分配给bits将值右移,并用正确的位数屏蔽它。这(1 << (hi - lo + 1)) - 1将 1 左移多于字段中的位数,然后减 1,为字段中的每个位位置生成一串二进制 1。例如,对于 hi = 2、lo = 0,将 1 左移 3 位,得到二进制 1000;减 1 得到 0111,因此选择了正确的 3 位。所以,bits包含 n 位整数的适当位组。

The if测试检查是否设置了 n 位整数的最高有效位。如果符号位未设置,我们只需返回该值bits。如果符号位被设置,那么我们就需要执行一个棘手的计算——这个计算在这个答案的初稿中是(非常)错误的。假设我们有一个 3 位字段 = 101。作为 3 位 2 的补码,表示 -3。我们需要将其向左扩展并全为 1 以生成全尺寸-1。的价值~0所有位均为 1;当它左移时hi - lo位,它为值的非符号位留下一系列零。如果你向左移动,它也会起作用hi - lo + 1,但是需要额外的计算+ 1那是没有必要的。

我使用这个测试工具来让自己确信代码工作正常。系统测试输出是严格的(针对较小的数字)。它确保计算值与预期值匹配。 “详尽”测试并不是真正详尽的。它只测试一个值,更多的是用于观察问题(例如在我的机器上使用 hi = 31 和 lo = 0 给出错误答案 0)和模式。

static const struct
{
    int  value;
    int  hi;
    int  lo;
    int  wanted;
} tests[] =
{
    {   0x0F,  1,  0,   -1 },
    {   0x0F,  2,  0,   -1 },
    {   0x0F,  2,  1,   -1 },
    {   0x0F,  3,  1,   -1 },
    {   0x0F,  4,  2,   +3 },
    {   0x0F,  5,  0,  +15 },
    {   0x0F,  5,  1,   +7 },
    {   0x0F,  5,  2,   +3 },
    {   0x0F,  5,  3,   +1 },
    {   0x0F,  5,  4,    0 },
    {   0x03,  2,  0,   +3 },
    {   0xF3,  2,  0,   +3 },
    {   0xF3,  3,  0,   +3 },
    {   0xF3,  4,  0,  -13 },
    {   0xF3,  5,  0,  -13 },
    {   0xF3,  6,  0,  -13 },
    {   0xF3,  7,  0,  -13 },
    {   0xF3,  7,  1,   -7 },
    {   0xF3,  7,  2,   -4 },
    {   0xF3,  7,  3,   -2 },
    {   0xF3,  7,  4,   -1 },
    {   0xF3,  8,  0, 0xF3 },
};
enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
static const char s_pass[] = "== PASS ==";
static const char s_fail[] = "!! FAIL !!";

static void systematic_test(void)
{
    int fail = 0;
    for (int i = 0; i < NUM_TESTS; i++)
    {
        char const *pf = s_fail;
        int actual = getFieldSignExtended(tests[i].value, tests[i].hi, tests[i].lo);
        if (actual == tests[i].wanted)
            pf = s_pass;
        else
            fail++;
        printf("%s GFSX(%+4d = 0x%.4X, %d, %d) = %+4d = 0x%.8X (wanted %+4d = 0x%.8X)\n",
               pf, tests[i].value, tests[i].value, tests[i].hi, tests[i].lo, actual, actual,
               tests[i].wanted, tests[i].wanted);
    }
    printf("%s\n", (fail == 0) ? s_pass : s_fail);
}

static void exhaustive_test(void)
{
    int value = 0x5FA03CE7;
    for (int i = 1; i < INT_BITS - 1; i++)
    {
        for (int j = 0; j < i; j++)
        {
            int actual = getFieldSignExtended(value, i, j);
            printf("%11sGFSX(%d = 0x%X, %2d, %2d) = %+10d = 0x%.8X\n", "",
                    value, value, i, j, actual, actual);
        }
    }
}

int main(void)
{
    int result1 = getFieldSignExtended(15, 2, 0);
    int result2 = getFieldSignExtended( 3, 2, 0);
    printf("GFSX(15, 2, 0) = %+d = 0x%.8X\n", result1, result1);
    printf("GFSX( 3, 2, 0) = %+d = 0x%.8X\n", result2, result2);

    printf("\nSystematic test\n");
    systematic_test();

    printf("\nExhaustive test\n");
    exhaustive_test();

    return(0);
}

这是详尽测试之前测试代码的输出,加上详尽测试输出的一小部分:

GFSX(15, 2, 0) = -1 = 0xFFFFFFFF
GFSX( 3, 2, 0) = +3 = 0x00000003

Systematic test
== PASS == GFSX( +15 = 0x000F, 1, 0) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 0) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 2, 1) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 3, 1) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX( +15 = 0x000F, 4, 2) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 0) =  +15 = 0x0000000F (wanted  +15 = 0x0000000F)
== PASS == GFSX( +15 = 0x000F, 5, 1) =   +7 = 0x00000007 (wanted   +7 = 0x00000007)
== PASS == GFSX( +15 = 0x000F, 5, 2) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX( +15 = 0x000F, 5, 3) =   +1 = 0x00000001 (wanted   +1 = 0x00000001)
== PASS == GFSX( +15 = 0x000F, 5, 4) =   +0 = 0x00000000 (wanted   +0 = 0x00000000)
== PASS == GFSX(  +3 = 0x0003, 2, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 2, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 3, 0) =   +3 = 0x00000003 (wanted   +3 = 0x00000003)
== PASS == GFSX(+243 = 0x00F3, 4, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 5, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 6, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 0) =  -13 = 0xFFFFFFF3 (wanted  -13 = 0xFFFFFFF3)
== PASS == GFSX(+243 = 0x00F3, 7, 1) =   -7 = 0xFFFFFFF9 (wanted   -7 = 0xFFFFFFF9)
== PASS == GFSX(+243 = 0x00F3, 7, 2) =   -4 = 0xFFFFFFFC (wanted   -4 = 0xFFFFFFFC)
== PASS == GFSX(+243 = 0x00F3, 7, 3) =   -2 = 0xFFFFFFFE (wanted   -2 = 0xFFFFFFFE)
== PASS == GFSX(+243 = 0x00F3, 7, 4) =   -1 = 0xFFFFFFFF (wanted   -1 = 0xFFFFFFFF)
== PASS == GFSX(+243 = 0x00F3, 8, 0) = +243 = 0x000000F3 (wanted +243 = 0x000000F3)
== PASS ==

Exhaustive test
       GFSX(1604336871 = 0x5FA03CE7,  1,  0) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  2,  0) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  2,  1) =         -1 = 0xFFFFFFFF
       GFSX(1604336871 = 0x5FA03CE7,  3,  0) =         +7 = 0x00000007
       GFSX(1604336871 = 0x5FA03CE7,  3,  1) =         +3 = 0x00000003
       GFSX(1604336871 = 0x5FA03CE7,  3,  2) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7,  4,  0) =         +7 = 0x00000007
       GFSX(1604336871 = 0x5FA03CE7,  4,  1) =         +3 = 0x00000003
       GFSX(1604336871 = 0x5FA03CE7,  4,  2) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7,  4,  3) =         +0 = 0x00000000
       GFSX(1604336871 = 0x5FA03CE7,  5,  0) =        -25 = 0xFFFFFFE7
       GFSX(1604336871 = 0x5FA03CE7,  5,  1) =        -13 = 0xFFFFFFF3
       GFSX(1604336871 = 0x5FA03CE7,  5,  2) =         -7 = 0xFFFFFFF9
       GFSX(1604336871 = 0x5FA03CE7,  5,  3) =         -4 = 0xFFFFFFFC
       GFSX(1604336871 = 0x5FA03CE7,  5,  4) =         -2 = 0xFFFFFFFE
       GFSX(1604336871 = 0x5FA03CE7,  6,  0) =        -25 = 0xFFFFFFE7
       GFSX(1604336871 = 0x5FA03CE7,  6,  1) =        -13 = 0xFFFFFFF3
       GFSX(1604336871 = 0x5FA03CE7,  6,  2) =         -7 = 0xFFFFFFF9
       GFSX(1604336871 = 0x5FA03CE7,  6,  3) =         -4 = 0xFFFFFFFC
       GFSX(1604336871 = 0x5FA03CE7,  6,  4) =         -2 = 0xFFFFFFFE
       GFSX(1604336871 = 0x5FA03CE7,  6,  5) =         -1 = 0xFFFFFFFF
...
       GFSX(1604336871 = 0x5FA03CE7, 29, 28) =         +1 = 0x00000001
       GFSX(1604336871 = 0x5FA03CE7, 30,  0) = -543146777 = 0xDFA03CE7
       GFSX(1604336871 = 0x5FA03CE7, 30,  1) = -271573389 = 0xEFD01E73
       GFSX(1604336871 = 0x5FA03CE7, 30,  2) = -135786695 = 0xF7E80F39
       GFSX(1604336871 = 0x5FA03CE7, 30,  3) =  -67893348 = 0xFBF4079C
       GFSX(1604336871 = 0x5FA03CE7, 30,  4) =  -33946674 = 0xFDFA03CE
       GFSX(1604336871 = 0x5FA03CE7, 30,  5) =  -16973337 = 0xFEFD01E7
       GFSX(1604336871 = 0x5FA03CE7, 30,  6) =   -8486669 = 0xFF7E80F3
       GFSX(1604336871 = 0x5FA03CE7, 30,  7) =   -4243335 = 0xFFBF4079
       GFSX(1604336871 = 0x5FA03CE7, 30,  8) =   -2121668 = 0xFFDFA03C
       GFSX(1604336871 = 0x5FA03CE7, 30,  9) =   -1060834 = 0xFFEFD01E
       GFSX(1604336871 = 0x5FA03CE7, 30, 10) =    -530417 = 0xFFF7E80F
       GFSX(1604336871 = 0x5FA03CE7, 30, 11) =    -265209 = 0xFFFBF407
       GFSX(1604336871 = 0x5FA03CE7, 30, 12) =    -132605 = 0xFFFDFA03
       GFSX(1604336871 = 0x5FA03CE7, 30, 13) =     -66303 = 0xFFFEFD01
       GFSX(1604336871 = 0x5FA03CE7, 30, 14) =     -33152 = 0xFFFF7E80
       GFSX(1604336871 = 0x5FA03CE7, 30, 15) =     -16576 = 0xFFFFBF40
       GFSX(1604336871 = 0x5FA03CE7, 30, 16) =      -8288 = 0xFFFFDFA0
       GFSX(1604336871 = 0x5FA03CE7, 30, 17) =      -4144 = 0xFFFFEFD0
       GFSX(1604336871 = 0x5FA03CE7, 30, 18) =      -2072 = 0xFFFFF7E8
       GFSX(1604336871 = 0x5FA03CE7, 30, 19) =      -1036 = 0xFFFFFBF4
       GFSX(1604336871 = 0x5FA03CE7, 30, 20) =       -518 = 0xFFFFFDFA
       GFSX(1604336871 = 0x5FA03CE7, 30, 21) =       -259 = 0xFFFFFEFD
       GFSX(1604336871 = 0x5FA03CE7, 30, 22) =       -130 = 0xFFFFFF7E
       GFSX(1604336871 = 0x5FA03CE7, 30, 23) =        -65 = 0xFFFFFFBF
       GFSX(1604336871 = 0x5FA03CE7, 30, 24) =        -33 = 0xFFFFFFDF
       GFSX(1604336871 = 0x5FA03CE7, 30, 25) =        -17 = 0xFFFFFFEF
       GFSX(1604336871 = 0x5FA03CE7, 30, 26) =         -9 = 0xFFFFFFF7
       GFSX(1604336871 = 0x5FA03CE7, 30, 27) =         -5 = 0xFFFFFFFB
       GFSX(1604336871 = 0x5FA03CE7, 30, 28) =         -3 = 0xFFFFFFFD
       GFSX(1604336871 = 0x5FA03CE7, 30, 29) =         -2 = 0xFFFFFFFE
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C 中对 int 进行符号扩展 的相关文章

  • C 编程 - 文件 - fwrite

    我有一个关于编程和文件的问题 while current NULL if current gt Id Doctor 0 current current gt next id doc current gt Id Doctor if curre
  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 按成员序列化

    我已经实现了template
  • HTTPWebResponse 响应字符串被截断

    应用程序正在与 REST 服务通信 Fiddler 显示作为 Apps 响应传入的完整良好 XML 响应 该应用程序位于法属波利尼西亚 在新西兰也有一个相同的副本 因此主要嫌疑人似乎在编码 但我们已经检查过 但空手而归 查看流读取器的输出字
  • OleDbDataAdapter 未填充所有行

    嘿 我正在使用 DataAdapter 读取 Excel 文件并用该数据填充数据表 这是我的查询和连接字符串 private string Query SELECT FROM Sheet1 private string ConnectStr
  • 关于 C++ 转换:参数 1 从“[some_class]”到“[some_class]&”没有已知的转换

    我正在研究 C 并且遇到了一个错误 我不知道确切的原因 我已经找到了解决方案 但仍然想知道原因 class Base public void something Base b int main Base b b something Base
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • C#中如何移动PictureBox?

    我已经使用此代码来移动图片框pictureBox MouseMove event pictureBox Location new System Drawing Point e Location 但是当我尝试执行时 图片框闪烁并且无法识别确切
  • 转发声明和包含

    在使用库时 无论是我自己的还是外部的 都有很多带有前向声明的类 根据情况 相同的类也包含在内 当我使用某个类时 我需要知道该类使用的某些对象是前向声明的还是 include d 原因是我想知道是否应该包含两个标题还是只包含一个标题 现在我知
  • 什么时候虚拟继承是一个好的设计? [复制]

    这个问题在这里已经有答案了 EDIT3 请务必在回答之前清楚地了解我要问的内容 有 EDIT2 和很多评论 有 或曾经 有很多答案清楚地表明了对问题的误解 我知道这也是我的错 对此感到抱歉 嗨 我查看了有关虚拟继承的问题 class B p
  • 这些作业之间是否存在顺序点?

    以下代码中的两个赋值之间是否存在序列点 f f x 1 1 x 2 不 没有 在这种情况下 标准确实是含糊不清的 如果你想确认这一点 gcc 有这个非常酷的选项 Wsequence point在这种情况下 它会警告您该操作可能未定义
  • Windows 窗体:如果文本太长,请添加新行到标签

    我正在使用 C 有时 从网络服务返回的文本 我在标签中显示 太长 并且会在表单边缘被截断 如果标签不适合表单 是否有一种简单的方法可以在标签中添加换行符 Thanks 如果您将标签设置为autosize 它会随着您输入的任何文本自动增长 为
  • 对现有视频添加水印

    我正在寻找一种用 C 在视频上加水印的方法 就像在上面写文字一样 图片或文字标签 我该怎么做 谢谢 您可以使用 Nreco 视频转换器 代码看起来像 NReco VideoConverter FFMpegConverter wrap new
  • 如何从两个不同的项目中获取文件夹的相对路径

    我有两个项目和一个共享库 用于从此文件夹加载图像 C MainProject Project1 Images 项目1的文件夹 C MainProject Project1 Files Bin x86 Debug 其中有project1 ex
  • 通过指向其基址的指针删除 POD 对象是否安全?

    事实上 我正在考虑那些微不足道的可破坏物体 而不仅仅是POD http en wikipedia org wiki Plain old data structure 我不确定 POD 是否可以有基类 当我读到这个解释时is triviall
  • 将控制台重定向到 .NET 程序中的字符串

    如何重定向写入控制台的任何内容以写入字符串 对于您自己的流程 Console SetOut http msdn microsoft com en us library system console setout aspx并将其重定向到构建在
  • C# 成员变量继承

    我对 C 有点陌生 但我在编程方面有相当广泛的背景 我想做的事情 为游戏定义不同的 MapTiles 我已经像这样定义了 MapTile 基类 public class MapTile public Texture2D texture pu
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • Windows 和 Linux 上的线程

    我在互联网上看到过在 Windows 上使用 C 制作多线程应用程序的教程 以及在 Linux 上执行相同操作的其他教程 但不能同时用于两者 是否存在即使在 Linux 或 Windows 上编译也能工作的函数 您需要使用一个包含两者的实现
  • 如何防止用户控件表单在 C# 中处理键盘输入(箭头键)

    我的用户控件包含其他可以选择的控件 我想实现使用箭头键导航子控件的方法 问题是家长控制拦截箭头键并使用它来滚动其视图什么是我想避免的事情 我想自己解决控制内容的导航问题 我如何控制由箭头键引起的标准行为 提前致谢 MTH 这通常是通过重写

随机推荐