- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
这个问题的灵感来自 StackOverflow 的其他问题。今天,在浏览 StackOverflow 时,我遇到了一个问题,即通过值 k 对变量进行位移,该值 >= 该变量的宽度(以位为单位)。这意味着将 32 位 int 移动 32 位或更多位。
Left shift an integer by 32 bits
Unexpected C/C++ bitwise shift operators outcome
从这些问题中可以明显看出,如果我们尝试将一个数字移位 >= 变量位宽的 k 位,则只会采用最低有效的 log2k 位。对于 32 位的 int,最低有效 5 位被屏蔽并作为移位量。
所以一般来说,如果 w = 变量的宽度(以位为单位),x >> k
变成 x >> (k % w)
对于 int
,这是 x >> (k % 32)
。
The count is masked to five bits, which limits the count range to 0 to 31.
所以我编写了一个小程序来观察理论上应该产生的行为。我在评论中写下了结果转移量 % 32。
#include <stdio.h>
#include <stdlib.h>
#define PRINT_INT_HEX(x) printf("%s\t%#.8x\n", #x, x);
int main(void)
{
printf("==============================\n");
printf("Testing x << k, x >> k, where k >= w\n");
int lval = 0xFEDCBA98 << 32;
//int lval = 0xFEDCBA98 << 0;
int aval = 0xFEDCBA89 >> 36;
//int aval = 0xFEDCBA89 >> 4;
unsigned uval = 0xFEDCBA89 >> 40;
//unsigned uval = 0xFEDCBA89 >> 8;
PRINT_INT_HEX(lval)
PRINT_INT_HEX(aval)
PRINT_INT_HEX(uval)
putchar('\n');
return EXIT_SUCCESS;
}
并且输出与移位指令的预期行为不匹配!
==============================
Testing x << k, x >> k, where k >= w
lval 00000000
aval 00000000
uval 00000000
============================================= ======================
其实我对 Java 有点困惑。在 C/C++ 中,将 int 移动大于位宽的位数可能会减少 k % w,但这不是 C 标准所保证的。没有规定说这种行为应该一直发生。这是未定义的行为。
但是,在Java中就是这样。这是 Java 编程语言的规则。
Bitshift operators description in Java language specification
最佳答案
链接的问题明确指出,移位量大于被移位类型的位宽会调用 undefined behavior ,该标准将其定义为“使用不可移植或错误的程序构造或错误数据时的行为,本国际标准对此没有强加任何要求”
当您调用未定义的行为时,任何事情都可能发生。程序可能会崩溃,可能会输出奇怪的结果,或者看起来工作正常。此外,如果您使用不同的编译器或在同一编译器上使用不同的优化设置,未定义行为的表现方式也会发生变化。
C 标准在第 6.5.7p3 节中对位移运算符作了如下说明:
The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
在这种情况下,编译器可能会像您建议的那样减少以位宽为模的移位量,或者它可以将其视为数学上移位该量导致所有位为 0。两者都是有效结果,因为该标准未指定行为。
关于c - 为什么将变量移位超过其位宽度会清零?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51145636/
我想将这个无符号数:1479636484000 向右移动 7 位。这在 JavaScript 中可能吗? 两者 1479636484000 >> 7 和 1479636484000 >>> 7 返回错
鉴于以下代码: import matplotlib.pyplot as plt import numpy as np x = [1.0, 1.1, 2.0, 5.7] y = np.arange(le
我有一个低级键盘钩子(Hook),目前允许我从任何应用程序(包括游戏)中控制媒体播放器。 它通过查看捕获的特定击键来工作。 我想扩展它以查找键的组合。我可以对一些逻辑进行硬编码,但我觉得必须有一种更合
我需要一些帮助来理解这段C代码。我不知道这里的“L”和“\”是什么?请也说明一点:) #define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>2
我正在查看一段代码: int result = 0 ; char byte = foo[j] for (i = 7 ; i>0 ; i--) { byte = (byte & ~0x1)>>1
我们有一个项目要求我们编写一个程序,允许用户输入一系列数字“将数字读入数组以进行进一步处理,用户通过输入负数表示他们已完成(负数不用于计算),在读取所有数字后执行以下操作,总结输入的#,计算输入的#,
锁定。有disputes about this question’s content正在解决中。它目前不接受新的答案或互动。 def menu(): choice = input("Pres
为什么如果 int x = -1 // binary: 11111111111111111111111111111111 x = x >>> 31; 我们有 000000000000000000000
我的问题其实应该很简单:我有一个玩家对象数组。(玩家[])我想要一个函数来旋转这个数组直到一个索引: public void rotateArray(Object[] array, int index
我有一个编码为 boost 动态位集的数字列表。我根据此列表中的任何数字可以采用的最大值动态选择此位集的大小。所以假设我有从 0 到 7 的数字,我只需要三位,我的字符串 0,2,7 将被编码为000
我能想到一些令人讨厌的低效方法来完成这项任务,但我想知道最好的方法是什么。 例如,我想复制一个字节中从第 3 位开始的 10 个字节,并像往常一样复制到一个指针。 有没有比一次复制一个移位字节更好的方
我正在尝试为该问题添加更多规则,并且该规则一直给我带来这种转变/减少冲突的能力,我不知道为什么会这样做,并且在过去的24小时内我一直在尝试解决问题 FuncDecl : RetTyp
This question already has answers here: Why does it make a difference if left and right shift are us
我在 Perl 中遇到这个问题已经有几天了,在搜索了无数的手册页、perldocs 和谷歌搜索了太多的搜索词之后,希望这里有人能帮助我。 我得到两个表示十六进制值的字符串,即“FFFF”,而不是 Pe
我有一个主 div,两个 div 水平并排放置在这个父 div 中。 .parent{ height: 360px; margin-top: 0px; bo
我想 float 我的元素列表并从第二个元素创建一个移动效果。 如何避免第二个 .item 之后的“清除”行为? .shift { float: right; width: 50%;
我正在使用 SSE3 优化我的代码。代码中有一点迫使我将 vector 中的所有元素移动一个元素 v[0] = 0 //v is some char* and N = v.size() for(i
.file "calcnew.c" .text .globl calcnew .type calcnew, @function calcnew:
我有一个点对象: class Point { final int x,y; ... } 因为这些点将在我的代码中到处使用/创建,所以我想开始使用 guavas 缓存。不幸的是
x = "Foo 890 bar *()" 如何将包括 "*()" 在内的小写字母“未移位”返回到 890?期望的结果: foo 890 bar 890 不需要的: x.lower() => "foo
我是一名优秀的程序员,十分优秀!