在C中,移位运算符(<<,>>)是算术还是逻辑?
我知道有>>符号整数的行为可以依赖于实现(具体来说,当左操作数为负时).
怎么样的人:~,>>,&,^,|?当他们的操作数有符号内建类型(整数short,int,long,long long),都将结果保证是相同的(中位含量),好像他们的类型是无符号的?
我有一个关于Delphi中位移行为的问题(或者更可能是错误报告)(在Borland Delphi 7中测试过).
目标:使用任意数字向右执行"算术"按位移位.
这意味着必须扩展符号位 - 如果设置了一个数字的最高有效位,则将从左侧填充二进制数,而不是0.
因此,算术右移后的数字"-1"必须保持相同的数字(所有位= 1),但是"逻辑移位"(总是用零填充数字)必须给出最大正整数(最大正有符号整数) ,为了正确)
我只在32位系统上测试过它(Windows); 而且,我需要它以32位整数显式工作.
当源编号存储在变量中时,看起来Delphi中存在带有"shr"的内部错误.
我的示例代码:
program bug;
{$APPTYPE CONSOLE}
var
I:Integer;
C:Cardinal;
begin
I := -1; // we’ll need that later
C := $FFFFFFFF;
Run Code Online (Sandbox Code Playgroud)
(这只是开始).接下来,让我们尝试一些"shr":
Writeln('0) ', -1 shr 1 );
Writeln('1) ', $FFFFFFFF shr 1 );
Run Code Online (Sandbox Code Playgroud)
"-1"是等效于"$ FFFFFFFF"的签名.似乎"shr"行为(算术或逻辑)基于源号是签名还是不签名(整数或基数)的事实.
输出是:
0) -1
1) 2147483647
Run Code Online (Sandbox Code Playgroud)
非常正确.然后我需要尝试手动将这些数字转换为整数或基数:
Writeln('2) ', Integer(-1) shr 1 );
Writeln('3) ', Integer($FFFFFFFF) shr 1 );
Writeln('4) ', Cardinal(-1) shr 1 );
Writeln('5) ', Cardinal($FFFFFFFF) shr 1 ); …Run Code Online (Sandbox Code Playgroud) int v, sign;
// or, to avoid branching on CPUs with flag registers (IA32):
sign = -(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)); // if v < 0 then -1, else 0.
Run Code Online (Sandbox Code Playgroud)
此语句为变量符号指定变量v的符号(-1或0).我想知道为什么(int)((unsigned int)((int)v)用而不是普通的v?
在Linux 内核中,我找到了以下代码:
static inline loff_t pos_from_hilo(unsigned long high, unsigned long low)
{
#define HALF_LONG_BITS (BITS_PER_LONG / 2)
return (((loff_t)high << HALF_LONG_BITS) << HALF_LONG_BITS) | low;
}
Run Code Online (Sandbox Code Playgroud)
该代码用于将系统调用参数组合成一个更宽的变量,因此例如在 ia32 上,偏移量pwritev在两个 32 位寄存器中指定。
在 x64 上,loff_t并且unsigned long都是 64 位宽。在这种情况下,high变量将被忽略并仅low被使用。在 ia32 上,loff_t是 64 位宽和unsigned long32 位宽。在这种情况下,两个参数high和low组合在一起。
我想知道为什么代码移位两次而不是一次。在提交消息和 LWN 文章中有更多关于此代码的信息:系统调用和 64 位体系结构,但没有解释双位移位。
所以,假设我有一个有符号整数(几个例子):
-1101363339 = 10111110 01011010 10000111 01110101 in binary.
-2147463094 = 10000000 00000000 01010000 01001010 in binary.
-20552 = 11111111 11111111 10101111 10111000 in binary.
Run Code Online (Sandbox Code Playgroud)
现在:-1101363339 >> 31例如,应该等于1对吗?但在我的电脑上,我得到-1.无论我选择什么负整数,如果x =负数,x >> 31 = -1.为什么?显然是二进制的,它应该是1.
请考虑以下示例:
第一个案例:
short x=255;
x = (x<<8)>>8;
cout<<x<<endl;
Run Code Online (Sandbox Code Playgroud)
第二种情况:
short x=255;
x = x<<8;
x = x>>8;
cout<<x<<endl;
Run Code Online (Sandbox Code Playgroud)
第一种情况下的输出是255,而第二种情况下的输出是-1.-1因为输出确实有意义,因为cpp进行算术右移.以下是获取-1作为输出的x的中间值.
x: 0000 0000 1111 1111
x<<8:1111 1111 0000 0000
x>>8:1111 1111 1111 1111
Run Code Online (Sandbox Code Playgroud)
为什么在第一种情况下不会发生相同的机制?
我正在运行一个快速测试,以确保我的指针算术运算:
main.c中
#include <stdio.h>
#include <stdlib.h>
#define ADDRESS 0xC0DCA11501LL
#define LENGTH 5
void print_address( char *, char );
/* Main program */
int main( int argc, char *argv[] )
{
char nums[ LENGTH ];
/* LSB first */
for( int i = 0; i < LENGTH; i++ )
{
nums[ i ] = ( ADDRESS >> ( 8 * i ) ) & 0xFF;
}
print_address( nums, LENGTH );
system("PAUSE");
return 0;
}
void print_address( char *data, char len ) …Run Code Online (Sandbox Code Playgroud) 我尝试在C中按位操作.这是我的代码:
int main() {
char c = 127;
c <<= 1;
if (c == 0xfe) {
printf("yes");
}
else {
printf("No");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
系统控制台打印否.我希望收到的是是.位移后c中的值为ffffffffe.似乎系统已经将8位改为32位.谁能帮我.
c bit-manipulation type-conversion integer-promotion type-promotion
我正在编写一个C ++程序,并且需要一个在所有现有的“ 1”之后将所有9位都设置为1的函数。
也就是说,我要编写一个void set10BitsFull(int64_t& n)将整数“ int64_t n = 0b...1000000000...” set10BitsFull(n)转换n为“ 0b...1111111111...” 的函数。
(更新)将输入整数的位稀疏地设置为1,并且两个1之间至少有10位距离。对于样本输入0x20000200,期望的输出为0x3FF003FF。最后1个位之后将至少有9位0。最左边的10位将始终为零。
这是我对该功能的实现
/**
* Inline function that set 10 bits to 1 after each set 1
* i.e.,
* ......1000000000...... -> ......1111111111.......
*
* @param n
* pointer of input number
*/
inline void set10BitFull(int_fast64_t *n) {
// n = 1000000000
*n |= (*n >> 1); // n = 1100000000
*n |= (*n >> 2) | …Run Code Online (Sandbox Code Playgroud) 我试图平均两种颜色.
我原来的(可怕的)工具如下:
//color is a union
int ColorAverage(int c1, int c2) {
color C1(c1);
color C2(c2);
return color(
(unsigned char)(0.5f * C1.a + 0.5f * C2.a),
(unsigned char)(0.5f * C1.r + 0.5f * C2.r),
(unsigned char)(0.5f * C1.g + 0.5f * C2.g),
(unsigned char)(0.5f * C1.b + 0.5f * C2.b)
).c;
}
Run Code Online (Sandbox Code Playgroud)
我目前的解决方案如下(表现更好):
int ColorAverage(int c1, int c2) {
unsigned char* b1 = reinterpret_cast<unsigned char*>(&c1);
unsigned char* b2 = reinterpret_cast<unsigned char*>(&c2);
int value;
unsigned char* bv = reinterpret_cast<unsigned char*>(&value);
bv[0] …Run Code Online (Sandbox Code Playgroud) 该博客声称:
- 未定义的行为仅在高优化级别(例如 -O2 或 -O3)下“发生”。
- 如果我使用 -O0 之类的标志关闭优化,那么就没有 UB。
都是假的。我想知道是否有任何现实世界的展示可以证明这一点。
例如,n << 1当 时触发 UB n<0。对于以下函数:
void foo(int n) {
int t = n<<1;
if (n>=0)
nuke();
}
Run Code Online (Sandbox Code Playgroud)
编译器可以谨慎地编译它:
void foo(int n) {
int t = n>=0 ? (n*2) : error("lshift negative int");
if (n>=0)
nuke();
}
Run Code Online (Sandbox Code Playgroud)
或通常:
void foo(int n) {
int t = n*2;
if (n>=0)
nuke();
}
Run Code Online (Sandbox Code Playgroud)
或者积极优化它:
void foo(int n) {
// unused
// int t = n<<1;
// always true, otherwise …Run Code Online (Sandbox Code Playgroud)