-20左移3位的结果到底是-32还是-160 求详细分析,谢谢

小龙王2010 2013-01-16 03:38:24
-20的补码: 1110 1100
现在要计算 -20<<3 的值
我按照左移规则 来推理
由 -20<<3 得到 1110 0000
1110 0000 是补码形式, 要求得其原码 则对其求补: 1010 0000 由此我计算的结果是 -32 但是程序运行的结果是 -160 这是怎么来的, 请高人指点, 谢谢
...全文
600 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2014-01-13
  • 打赏
  • 举报
回复
C++ Integer Constants Integer constants are constant data elements that have no fractional parts or exponents. They always begin with a digit. You can specify integer constants in decimal, octal, or hexadecimal form. They can specify signed or unsigned types and long or short types. Syntax integer-constant : decimal-constant integer-suffixopt octal-constant integer-suffixopt hexadecimal-constant integer-suffixopt 'c-char-sequence' decimal-constant : nonzero-digit decimal-constant digit octal-constant : 0 octal-constant octal-digit hexadecimal-constant : 0x hexadecimal-digit 0X hexadecimal-digit hexadecimal-constant hexadecimal-digit nonzero-digit : one of 1 2 3 4 5 6 7 8 9 octal-digit : one of 0 1 2 3 4 5 6 7 hexadecimal-digit : one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F integer-suffix : unsigned-suffix long-suffixopt long-suffix unsigned-suffixopt unsigned-suffix : one of u U long-suffix : one of l L 64-bit integer-suffix : i64 To specify integer constants using octal or hexadecimal notation, use a prefix that denotes the base. To specify an integer constant of a given integral type, use a suffix that denotes the type. To specify a decimal constant, begin the specification with a nonzero digit. For example: int i = 157; // Decimal constant int j = 0198; // Not a decimal number; erroneous octal constant int k = 0365; // Leading zero specifies octal constant, not decimal To specify an octal constant, begin the specification with 0, followed by a sequence of digits in the range 0 through 7. The digits 8 and 9 are errors in specifying an octal constant. For example: int i = 0377; // Octal constant int j = 0397; // Error: 9 is not an octal digit To specify a hexadecimal constant, begin the specification with 0x or 0X (the case of the “x” does not matter), followed by a sequence of digits in the range 0 through 9 and a (or A) through f (or F). Hexadecimal digits a (or A) through f (or F) represent values in the range 10 through 15. For example: int i = 0x3fff; // Hexadecimal constant int j = 0X3FFF; // Equal to i To specify an unsigned type, use either the u or U suffix. To specify a long type, use either the l or L suffix. For example: unsigned uVal = 328u; // Unsigned value long lVal = 0x7FFFFFL; // Long value specified // as hex constant unsigned long ulVal = 0776745ul; // Unsigned long value
yan2anfei 2014-01-13
  • 打赏
  • 举报
回复
引用 20 楼 zhao4zhong1 的回复:
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
#include <stdio.h>
unsigned short int ui;
  signed short int si;
int main() {
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui>>1;
    si=si>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed short int)ui)>>1;
    si=((unsigned short int)si)>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("==============\n");

    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui<<1;
    si=si<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed short int)ui)<<1;
    si=((unsigned short int)si)<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    return 0;
}
//ui=32768
//si=-32768
//ui=16384
//si=-16384
//--------------
//ui=32768
//si=-32768
//ui=49152
//si=16384
//==============
//ui=32768
//si=-32768
//ui=0
//si=0
//--------------
//ui=32768
//si=-32768
//ui=0
//si=0
#include <stdio.h>
unsigned int ui;
  signed int si;
int main() {
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui>>1;
    si=si>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed int)ui)>>1;
    si=((unsigned int)si)>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("==============\n");

    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui<<1;
    si=si<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed int)ui)<<1;
    si=((unsigned int)si)<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    return 0;
}
//ui=2147483648
//si=-2147483648
//ui=1073741824
//si=-1073741824
//--------------
//ui=2147483648
//si=-2147483648
//ui=3221225472
//si=1073741824
//==============
//ui=2147483648
//si=-2147483648
//ui=0
//si=0
//--------------
//ui=2147483648
//si=-2147483648
//ui=0
//si=0
ui=(unsigned short int)0x8000u; 谁给小弟讲讲这个U是什么意思啊,谢谢
swordtan 2013-01-17
  • 打赏
  • 举报
回复
c99标准 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 ´ 2E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 ´ 2E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
BlackGhost 2013-01-17
  • 打赏
  • 举报
回复
符号位的移动 是实现决定吧
千树之影 2013-01-17
  • 打赏
  • 举报
回复
楼主从根本上就错了,负数左移是连符号位一起移的! 不信输出 (-20)<<27试试就知道了,结果是个正数。
小布 2013-01-17
  • 打赏
  • 举报
回复
引用 2 楼 ganpengjin1 的回复:
这是int类型,不是char类型,所以它占了32位,而不是8位,你把它们补齐就知道答案了,是-160的。
楼主知道有默认类型转换的
赵4老师 2013-01-17
  • 打赏
  • 举报
回复
补充char版:
#include <stdio.h>
unsigned char ui;
  signed char si;
char main() {
    ui=(unsigned char)0x80u;
    si=(  signed char)0x80;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui>>1;
    si=si>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned char)0x80u;
    si=(  signed char)0x80;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed char)ui)>>1;
    si=((unsigned char)si)>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("==============\n");

    ui=(unsigned char)0x80u;
    si=(  signed char)0x80;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui<<1;
    si=si<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned char)0x80u;
    si=(  signed char)0x80;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed char)ui)<<1;
    si=((unsigned char)si)<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    return 0;
}
//ui=128
//si=-128
//ui=64
//si=-64
//--------------
//ui=128
//si=-128
//ui=192
//si=64
//==============
//ui=128
//si=-128
//ui=0
//si=0
//--------------
//ui=128
//si=-128
//ui=0
//si=0
小龙王2010 2013-01-17
  • 打赏
  • 举报
回复
21楼的zhao4zhong1 兄弟说得十分到位, 小弟学习了, 非常感谢
小龙王2010 2013-01-17
  • 打赏
  • 举报
回复
在32位的XP系统中 -20的原码:1000 0000 0000 0000 0000 0000 0001 0100 -20的反码:1111 1111 1111 1111 1111 1111 1110 1011 -20的补码:1111 1111 1111 1111 1111 1111 1110 1100 -20<<3 即 -20左移3位 ,左移低位补0 ,得到: 1 1111 1111 1111 1111 1111 1110 1100 000 即1111 1111 1111 1111 1111 1111 0110 0000 特别注意:1.这个结果目前保存在CPU的寄存器中;2.此时的结果是补码形式,要求得最后的结果,还要对其求补,以上式子求补之后得到: 1000 0000 0000 0000 0000 0000 1010 0000 那么此时的二进制值转为十进制则为:-160 如果是下面的情况则是: char a = -20 ; cout<< a<<3<<endl; 则输出的还是 -160,就是上面的分析结果 因为 char 类型的值 先转为int 型 ,就是从char型的8位 扩充到 int 型的 32位计算, 还有就是我们上面提到的特别注意两点中第一点:a<<3 运算的结果是保存在cpu的寄存器中,而不是保存在a中,所以 输出a<<3的值并不等于是输出a本身的值,为什么要这样讲? 因为 a 是char型, 只有8位 , 那么它的取值范围只有 -128 到 127 现在输出的是 -160 明显超出了它的取值范围, 所以你若认为此时输出的是a的值就不能理解了,而实际它输出的是保存在CPU寄存器中的这个表达式a<<3提升为int型的值。你若还不能理解,请看下面: char b = -20; b = b<<3; cout<<b<<endl; 你猜现在会输出什么东西? 它输出一个类型英文所有格中右上角的那个一点的符号 如: ’ 为什么输出的是符号 而不是数字和其他的东西?我们查ASCII表,得到 这个 ‘ 在ASCII表中所对应的十进制是:96 十六进制是:60 二进制是 :0110 0000 ? 这个二进制的形式貌似在哪见过吧? 就是见过, 分析和上面一样: b<<3 得到的结果还是和上面一样为: 1111 1111 1111 1111 1111 1111 0110 0000 此时你看地8位是不是就是上面的b输出的那个图像对应的二进制啊? 没错,就是的, 因为 b<<3 的运算结果是保存在CPU寄存器中,不是在char型的b中, 现在我们用 b = b<<3: 把这个CPU寄存器中的值强行保存到b中, 但是cpu寄存器中的这个值是32位的就是上面求得的那个补码,而b只有8位,且一切数据在计算机内的表示形式是补码的形式进行存储和表示的, 所以这里就只能装下低8位 (为什么不装高8位,我想这个和数据大小端存储模式是有关,你可以查一下大小端存储并检测你的32位系统是什么端存储)装下的低8位就是 0110 0000 其它位丢失, 看这底8位中的最高位是0 , 即符号位是0 所以变成了正数, 正数原码反码补码相同, 所以这个底8位的补码形式也是它的原码形式, 所以我们计算得到 64 + 32 = 96 这也就解释了输出的那个图形为什么对应ASCII表中的十进制96了 这个问题 全面解析完毕, 谢谢大家的帮忙, 谢谢大家
小龙王2010 2013-01-17
  • 打赏
  • 举报
回复
14楼的兄弟说的对, char 移位运算之后先转换成了 int 才能运行 在移位运算时,byte、short和char类型移位后的结果会变成int类型,对于byte、short、char和int进行移位时,规定实际移动的次数是移动次数和32的余数,也就是移位33次和移位1次得到的结果相同。移动long型的数值时,规定实际移动的次数是移动次数和64的余数,也就是移动66次和移动2次得到的结果相同
赵4老师 2013-01-17
  • 打赏
  • 举报
回复
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行!
赵4老师 2013-01-17
  • 打赏
  • 举报
回复
不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实!
#include <stdio.h>
unsigned short int ui;
  signed short int si;
int main() {
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui>>1;
    si=si>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed short int)ui)>>1;
    si=((unsigned short int)si)>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("==============\n");

    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui<<1;
    si=si<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned short int)0x8000u;
    si=(  signed short int)0x8000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed short int)ui)<<1;
    si=((unsigned short int)si)<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    return 0;
}
//ui=32768
//si=-32768
//ui=16384
//si=-16384
//--------------
//ui=32768
//si=-32768
//ui=49152
//si=16384
//==============
//ui=32768
//si=-32768
//ui=0
//si=0
//--------------
//ui=32768
//si=-32768
//ui=0
//si=0
#include <stdio.h>
unsigned int ui;
  signed int si;
int main() {
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui>>1;
    si=si>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed int)ui)>>1;
    si=((unsigned int)si)>>1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("==============\n");

    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=ui<<1;
    si=si<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    printf("--------------\n");
    ui=(unsigned int)0x80000000u;
    si=(  signed int)0x80000000;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);
    ui=((  signed int)ui)<<1;
    si=((unsigned int)si)<<1;
    printf("ui=%u\n",ui);
    printf("si=%d\n",si);

    return 0;
}
//ui=2147483648
//si=-2147483648
//ui=1073741824
//si=-1073741824
//--------------
//ui=2147483648
//si=-2147483648
//ui=3221225472
//si=1073741824
//==============
//ui=2147483648
//si=-2147483648
//ui=0
//si=0
//--------------
//ui=2147483648
//si=-2147483648
//ui=0
//si=0
  • 打赏
  • 举报
回复
引用 8 楼 zhaoxiatengkong_1 的回复:
对于 int型的分析 很到位,谢谢 但是 6楼的大哥 对于 char型分析 的结果和我在Eclipse中运行的结果 不一样 char a = -20; cout << "a<<3 : "<<(a<<3)<<endl; 运行结果: a<<3 : -160 请帮忙分析一下, 这是为什么? 因为 char 只占用了一个字节, 那就是 8位, 所以此……
lz不诧异 -160不在 char的表示范围之内么?
taodm 2013-01-16
  • 打赏
  • 举报
回复
因为楼主用的教材太烂了,竟然没告诉你这些算术运算至少要升级到int然后才开始运算。
小龙王2010 2013-01-16
  • 打赏
  • 举报
回复
为什么 a 运行的结果还是 160 啊? char 不是一个字节吗? 怎么和 int 一样啊? char a = -20; cout << "a<<3 : "<<(a<<3)<<endl; 运行结果: a<<3 : -160
阿麦 2013-01-16
  • 打赏
  • 举报
回复
5楼正解。 或者你强制转换成unsigned int 打印出16进制看看就更清楚了 int x = -20; printf_s("%8d %08x\n%8d %08x\n", x, (unsigned int)x, (x << 3), (unsigned int)(x << 3));
derekrose 2013-01-16
  • 打赏
  • 举报
回复
引用 9 楼 zhaoxiatengkong_1 的回复:
左移和右移 ,符号位都保存不变 对吗?
应该是这样的,符号位是不能移动的
derekrose 2013-01-16
  • 打赏
  • 举报
回复
160-32=128 说明第八位有问题,第八位被你吞了
小龙王2010 2013-01-16
  • 打赏
  • 举报
回复
左移和右移 ,符号位都保存不变 对吗?
小龙王2010 2013-01-16
  • 打赏
  • 举报
回复
对于 int型的分析 很到位,谢谢 但是 6楼的大哥 对于 char型分析 的结果和我在Eclipse中运行的结果 不一样 char a = -20; cout << "a<<3 : "<<(a<<3)<<endl; 运行结果: a<<3 : -160 请帮忙分析一下, 这是为什么? 因为 char 只占用了一个字节, 那就是 8位, 所以此时值为 -20 的a 在内存中的表示为 : 1110 1100 转换之后的结果,我分析的应该是 1 1100 000 可是六楼的兄弟分析的结果是: 0X60 为96 但是实际在Eclipse中运行的结果还是 -160 请问这时怎么回事啊? 请求详细分析, 谢谢
加载更多回复(7)

64,281

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧