首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >K&R练习2-6 :将位集的一部分插入另一位集

K&R练习2-6 :将位集的一部分插入另一位集
EN

Code Review用户
提问于 2018-06-10 20:27:54
回答 1查看 199关注 0票数 3

将位集的一部分“插入”到另一个

这是关于K&R书第二版的练习2-6。请读者:

编写函数集位(x,p,n,y),返回x,从位置p开始到y的最右边的n位,而其他位不变。

参数描述

以下是每个参数的非正式操作:

  • X ->用作“目标”位集。
  • Y ->充当“源”位集。
  • P ->作为从y插入x的位的插入点。
  • N ->作为段的长度从y中“剪切”并在x中替换。

特别说明

  • 我使用了许多不同的场景进行了测试,这段代码已经通过了所有这些方案。
  • 在问题的底部,有一个测试用例的大纲,以及我解决问题的逻辑

代码语言:javascript
运行
复制
#include <stdio.h>

//setbits: returns x with n bits that begin at p set to the rightmost n bits of y
//informally: "chop" n bits right->left from y, insert on x at position p
unsigned setbits(unsigned x, int p, int n, unsigned y)
{
    return ((~(~0 << n) & y) << p) | ((~(~(~0 << n) << p)) & x);
}

int main(void) {
    // Example test cases:
    // First scenario:
    // x = 100 ->           0110 0100
    // y = 5 ->             0000 0101
    // p = 4
    // n = 3
    // Expected outcome:    0101 0100  (84)
    // Second scenario:
    // x = 94 ->            0101 1110
    // y = 195 ->           1100 0011
    // p = 0
    // n = 3
    // Expected outcome:    0101 1011  (91)
    // Third scenario:
    // x = 94 ->            0101 1110
    // y = 195 ->           1100 0011
    // p = 6 
    // n = 4
    // Expected outcome:    1101 1110  (222)

    printf("%d\n", setbits(100, 4, 3, 5));
    printf("%d\n", setbits(94, 0, 3, 195));
    printf("%d\n", setbits(94, 6, 4, 195));

    return 0;
}

大纲

点击获取全尺寸图像

EN

回答 1

Code Review用户

回答已采纳

发布于 2018-06-12 22:09:55

避免UB

1移到符号位置是未定义的行为(UB)。(C11§6.5.7 4)相反,使用无符号类型。0是一个int常数。0u是一个unsigned常数。

代码语言:javascript
运行
复制
// return ((~(~0 << n) & y) << p) | ((~(~(~0 << n) << p)) & x);
return ((~(~0u << n) & y) << p) | ((~(~(~0u << n) << p)) & x);

清晰度

代码清晰,让编译器形成最优的代码。

代码语言:javascript
运行
复制
// return ((~(~0u << n) & y) << p) | ((~(~(~0u << n) << p)) & x);
unsigned new_mask = ~(~0u << n);
unsigned old_mask = ~(mask << p);
return ((new_mask & y) << p) | (old_mask & x);

规范匹配

带有"%d"unsigned应该会引发编译器警告/注释。启用所有编译器警告,以避免如此容易识别的问题。

代码语言:javascript
运行
复制
// printf("%d\n", setbits(100, 4, 3, 5));
printf("%u\n", setbits(100, 4, 3, 5));

对于此任务,使用"%4x"将比使用"%u"提供更多的信息。

扩展测试

“我使用了许多不同的场景进行了测试,这段代码已经通过了所有这些方案。”->用UINT_MAX, UINT_MAX-1, 1, 0进行测试将有助于检查函数的“角”。

文档限制

仅限于0 <= p < bit_width0 <= n < bit_width的代码。由于代码无法处理所有可能的输入值,说明限制会减少不正确的使用。

为所有可能的输入定义行为的优点是不需要列出限制,但可能不需要功能性的(以及代码过载)。

仍然很好的张贴限制。

在最后一点上,也许稍微重写一下代码是为了让人很容易地期望n == bit_width是有效的。

代码语言:javascript
运行
复制
// This assumes no padding in `unsigned`
#define UINT_BIT_WIDTH (CHAR_BIT * sizeof(unsigned))

unsigned setbits(unsigned x, int p, int n, unsigned y) {
  unsigned new_mask = n >= UINT_BIT_WIDTH ? UINT_MAX : ~(~0u << n);
  ...
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/196242

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档