关于c语言中负数位移位操作的漫谈

最近有个朋友在程序中使用了对16进制数做负数移位(编译器是gcc),本人最次产生好奇,所以研究了一些。

对一个数做负数位移位的操作是不规范的,但是是可行的。

具体例子:

char tmp = 0x10;

tmp = tmp << -1;

大家猜猜结果是什么,有人猜是tmp左移-1位不就是右移1位吗?结果是0x01?

很遗憾,电脑和人脑是不一样的。结果是0

为什么呢?为了找出原因,本人进行了一些小小的测试,并做出了有依据的结果。

由于知道+0和-0的区别,所以,我首先将tmp << -128(-128就是-0),和猜想的一样,结果是0x10

而-128的二进制是 1000 000b

继续,将tmp << -127,结果是0x20,左移了1位

-127的二进制是 1000 0001b

迫不及待,尝试 tmp << -126,结果是0x40,左移了2位

-126的二进制是 1000 0010b

这时,大家应该和我一样,看出了端倪,但是先不要说出来,先看看他们以同样的值向右移:

首先将tmp >> -128(-128就是-0),结果是0x10

而-128的二进制是 1000 000b

继续,将tmp >> -127,结果是0x08,右移了1位

-127的二进制是 1000 0001b

迫不及待,尝试 tmp >> -126,结果是0x04,右移了2位

-126的二进制是 1000 0010b

这时,大家可以大胆的的猜测了,移位操作中若移动的是一个负数,那么移动的位数以这个负数的二进制形式的低七位决定。

若还有猜疑,继续测试:

tmp << -255 结果为0x20,-255的二进制为0x1 0000 0001b

tmp << -511 结果为0x20, -511的二进制为0x10 0000 0001b

tmp << -1023 结果为0x20,-1023的二进制为0x100 0000 0001b

现在大家可以肯定的说:移位操作中若移动的是一个负数,那么移动的位数以这个负数二进制形式的低七位决定。(现在的longlong型长度貌似最大也只有到64位,若要达到128位,这个编译器就要修改了。)

由于本人水平有限,如有错误,请指正。本人不胜感激。

进一步深化,待续。。。

关于c语言中负数位移位操作的漫谈

时间: 2024-10-24 15:12:23

关于c语言中负数位移位操作的漫谈的相关文章

c语言中的位移位操作

先要了解一下C语言里全部的位运算都是指二进制数的位运算.即使输入的是十进制的数,在内存中也是存储为二进制形式. “<<”使用方法: 格式是:a<<m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向左移动m位,高位移出后,低位补0. “>>”使用方法: 格式是:a>>m,a和m必须是整型表达式,要求m>=0. 功能:将整型数a按二进制位向右移动m位,低位移出后,高位补0 C语言中的移位操作,内容不多.只是有些地方你不注意,就疏

【转】C语言中的左移与右移

先说左移,左移就是把一个数的所有位都向左移动若干位,在C中用<<运算符.例如: int i = 1;i = i << 2;  //把i里的值左移2位 也就是说,1的2进制是000...0001(这里1前面0的个数和int的位数有关,32位机器,gcc里有31个0),左移2位之后变成 000...0100,也就是10进制的4,所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了(有符号数不完全适用,因为左移有可能导致符号变化,下面解释原因) 需要注意的一个问题是int类型最左

关于c语言中的位运算。。。

位运算是一种针对二进制数的一种运算 位运算 共有六种 都有其对应得操作符号 &      (and)      位于 |        (or)         位或 ~      (not)        取反 ^       (xor)        异或 >>    (shr)    右移一位 <<    (shl)     左移一位 运算说明: === 1. and运算 === and运算通常用于二进制取位操作,例如一个数 and 1的结果就是取二进制的最末位.这可

原码、反码、补码相关内容以及Java语言中是以哪一种码表示的

计算机中的数字是以二进制方式存储的,第一个二进制位为符号位,0代表正数,1代表负数 原码.反码.补码是计算机中存储数字使用的编码 1.原码.反码.补码的概念 原码:符号位加上这个数绝对值 例如正整数1的8位二进制原码为 00000001      负整数-1的8为二进制原码为 10000001 反码:正数的反码就是其本身,负数的反码就是在原码的基础上除符号位外所有的位取反 例如正整数1的8位二进制原码为 00000001 则其反码还为 00000001  负整数-1的8为二进制原码为 10000

c语言中会遇到的面试题

预处理器(Preprocessor) 1 . 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题)         #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL我在这想看到几件事情:1) #define 语法的基本知识(例如:不能以分号结束,括号的使用,等等)2)懂得预处理器将为你计算常数表达式的值,因此,直接写出你是如何计算一年中有多少秒而不是计算出实际的值,是更清晰而没有代价的.3) 意识到这个表达式将使一个16位

C语言中函数参数为什么是由右往左入栈的?

先通过一个小程序来看一看: #include void foo(int x, int y, int z) { printf("x = %d at [%X]n", x, &x); printf("y = %d at [%X]n", y, &y); printf("z = %d at [%X]n", z, &z); } int main(int argc, char *argv[]) { foo(100, 200, 300);

C语言中如何获得文件大小

方法一: 获得文件大小需要用到2个函数:fseek() , ftell() fseek()函数: 原型:intfseek(FILE *stream, long offset, int fromwhere): 参数: stream: 第一个参数stream为文件指针 offset : 第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移 fromwhere: 第三个参数origin设定从文件的哪里开始偏移,可能取值为:SEEK_CUR. SEEK_END 或 SEEK_SET SEE

【 c语言中无符号和有符号的加法运算】【深入理解】--【sky原创】

原文:[ c语言中无符号和有符号的加法运算][深入理解]--[sky原创] 第一题 #include<stdio.h> int main() { unsigned int a=6; int b=-20; printf("%d\n",a+b); (a+b)>6? puts(">6"):puts("<=6"); return 0; } 答案是:>6 第二题 #include<stdio.h> int m

C语言中函数参数入栈的顺序 - Fangzhen - 博客园

.wiz-todo, .wiz-todo-img {width: 16px; height: 16px; cursor: default; padding: 0 10px 0 2px; vertical-align: -10%;-webkit-user-select: none;} .wiz-todo-label { display: inline-block; padding-top: 7px; padding-bottom: 6px; line-height: 1.5;} .wiz-todo