【发布时间】:2013-04-01 16:19:14
【问题描述】:
C 编程语言练习 2-7:
编写一个函数
invert(x,p,n),它返回x,其中n位开始于p位置反转(即1更改为0,反之亦然),其他保持不变。
我理解这样的问题:我有 182,即二进制的 101(101)10,括号中的部分必须反转而不改变其余部分。那么返回值应该是10101010,即十进制的170。
这是我的尝试:
#include <stdio.h>
unsigned int getbits(unsigned int bitfield, int pos, int num);
unsigned int invert(unsigned int bitfield, int pos, int num);
int main(void)
{
printf("%d\n", invert(182, 4, 3));
return 0;
}
/* getbits: get num bits from position pos */
unsigned int getbits(unsigned int bitfield, int pos, int num)
{
return (bitfield >> (pos+1-n)) & ~(~0 << num);
}
/* invert: flip pos-num bits in bitfield */
unsigned int invert(unsigned int bitfield, int pos, int num)
{
unsigned int mask;
unsigned int bits = getbits(bitfield,pos,num);
mask = (bits << (num-1)) | ((~bits << (pos+1)) >> num);
return bitfield ^ mask;
}
这似乎是正确的(对我来说),但 invert(182, 4, 3) 输出 536870730。 getbits() 工作正常(直接来自书中)。我写下了我分配给y的表达式中发生的事情:
(00000101 << 2) | ((~00000101 << 5) >> 3) -- 000000101 is the part being flipped: 101(101)10
00010100 | ((11111010 << 5) >> 3)
00010100 | (01000000 >> 3)
00010100 | 00001000
= 00011100
10110110 (182)
^ 00011100
----------
= 10101010 (170)
应该是正确的,但事实并非如此。我发现这是出错的地方:((~xpn << (p+1)) >> n)。我不明白怎么做。
另外,我不知道这段代码有多通用。我的首要任务是让这个案子运作起来。也欢迎在这个问题上提供帮助。
【问题讨论】:
-
不要给变量取诸如“x, p, n”之类的垃圾名称,这是一个非常糟糕的主意。
-
@Lundin K&R 这样命名它们,所以我也这样做了。尽管这背后可能有格式化的原因。我会记住这一点的。
-
是的,我意识到真正糟糕的想法来自 K&R。请注意,您无法从那本书中学到好的编程实践。对于已经过时 14 年的 C 语言版本,你只能从中学习语法。
-
@Lundin,这些变量名很好。 K&R 是正确的。根据定义。或者查看 Linux 内核 C 风格指南。
-
@vonbrand Err,不,我很抱歉,但在现代编程中,没有“定义正确,因为某些大师在 80 年代这样说”这样的东西。此外,程序员应该使用自己的大脑。如果您认为“x”是一个很棒的变量名,无论是否使用您的大脑,那就这样吧-在得出这样的结论之后不再讨论是没有意义的。至于 Linux 内核编码风格,它是一个相当非正式的文档,对于所陈述的模糊规则缺乏大量理由或来源。这当然不是某些 C 规范。如果您想要专业的编码标准,请查看 MISRA-C 或 CERT-C。
标签: c bit-manipulation kernighan-and-ritchie