高手们分析一下C++ 中short 型变量最大值加1后没有变负值,也不知道是BUG还是它理应如此(人穷没有分啊。高手们不要生气啊)

jingzizhuo 2008-04-12 09:03:41
各位高手请帮忙分析下:
以下代码均在Microsoft Visual Studio 2005和eclipse3.2.0+CDT+MinGW中编译过
代码如下:
#include <iostream>
#include <climits>
using namespace std;

int main()
{
int n_int=INT_MAX;
short n_short=SHRT_MAX;
long n_long=LONG_MAX;
unsigned int n_unsigned_int=n_int;
unsigned short n_unsigned_short=n_short;
unsigned long n_unsigned_long=n_long;
cout << "short is : " << sizeof(short) << "bytes.\n";
cout << "short is : " << sizeof(n_short) << " bytes.\n";
cout << "n_int: " << n_int;
cout << "\t\tn_short: " << n_short;
cout << "\t\tn_long: " << n_long << endl;
cout << "n_unsigned_int: " << n_unsigned_int;
cout << "\tn_unsigned_short: " << n_unsigned_short;
cout << "\tn_unsigned_long: " << n_unsigned_long << endl;

cout << "----------------变量加1后-----------------------------\n";
cout << "n_int + 1: " << (n_int + 1);
cout << "\t\tn_short + 1: " << (n_short + 1);
cout << "\t\tn_long +1: " << (n_long + 1) << endl;

cout << "n_unsigned_int+1: "<< (n_unsigned_int + 1);
cout << "\t\tn_unsigned_short+1: " << (n_unsigned_short + 1);
cout << "\t\tn_unsigned_long+1: " << (n_unsigned_long + 1);
cout << "\n--------unsigned型变量置0然后减去1后-----------------\n";
n_unsigned_int=0;
n_unsigned_short=0;
n_unsigned_long=0;
cout << "n_unsigned_int-1: "<< (n_unsigned_int - 1);
cout << "\t\tn_unsigned_short-1: " << (n_unsigned_short - 1);
cout << "\t\tn_unsigned_long-1: " << (n_unsigned_long - 1);

return 0;
}
在Microsoft Visual Studio 2005和eclipse3.2.0+CDT+MinGW中编译后结果如下:
short is : 2bytes.
n_int: 2147483647 n_short: 32767 n_long: 2147483647
n_unsigned_int: 2147483647 n_unsigned_short: 32767 n_unsigned_long: 2147483647
----------------变量加1后----------------------------
n_int + 1: -2147483648 n_short + 1: 32768 n_long +1: -2147483648
n_unsigned_int+1: 2147483648 n_unsigned_short+1: 32768 n_unsigned_long+1: 2147483648
--------unsigned型变量置0然后减去1后-----------------
n_unsigned_int-1: 4294967295 n_unsigned_short-1: -1 n_unsigned_long-1: 4294967295

问题出现在short型变量。给short型变量取最大值32767.我用的是C++内climits自定义的最大值SHRT_MAX。即然为最大值为什么加1后,结果没有像int型变量和long变量那样变为负值呢。难道short型变量占用了更多的字结。我就用sizeof()计算发现是2Byte.就不应该还能加上去呀。
----------------
随后又让无符号的 unsigned short -1后发现,居然能变成-1值来。晕到了。请各位高手们帮忙解析一下。为什么呢
...全文
1054 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 hityct1 的回复:]
也许是型别自动转换造成的。operator < < 有很多重载形式,很可能是编译器无法识别该用哪个。
强制转换一下:

cout < < "\t\tn_short + 1: " < <(short)(n_short + 1);

或者象第二个程序一样:

n_short=n_short+1;
cout < < "n_short最大值32767后加1: " < < n_short < < endl;
[/Quote]
嗯。你说的也很有理。可是已经结贴了,不然给你加点分。虽然只有区区20分。可是都没有了。后悔了
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
我的总结如下。long型和int型,由于占用空间一样的大,所以当int型和long型最大值加一后,结果都是向前循不了。而,short型。如果不进行类型限制,就会向容量更大类型提升。所以在cout对像中,使用了n_short+1,由于没有进行类型限制,所以向上提升了。而采用了n_short=n_short+1时,n_short为short型,所以进行了限制,计算机不会自动向上提升。
hityct1 2008-04-12
  • 打赏
  • 举报
回复
也许是型别自动转换造成的。operator << 有很多重载形式,很可能是编译器无法识别该用哪个。
强制转换一下:

cout<< "\t\tn_short + 1: " <<(short)(n_short + 1);

或者象第二个程序一样:

n_short=n_short+1;
cout << "n_short最大值32767后加1: " << n_short << endl;
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 jingzizhuo 的回复:]
引用 9 楼 ttkk_2007 的回复:
哥们,我不是跟你说了吗,已经提升了
(n_short + 1),一个short和int型相加,都提升为int了
你字节sizeof(n_short+1)看看,4个字节了,你怎么就不听我的呢
还C++的bug

----------
我知道啊。哦。终于明白了。 出丑了。终于明白了,怪不得
n_short=n_short就不会出现问题。原来它样做,就不会提升。谢谢大侠啊。
[/Quote]
打错了是n_short=n_short+1,不是n_short=n_short
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 ttkk_2007 的回复:]
哥们,我不是跟你说了吗,已经提升了
(n_short + 1),一个short和int型相加,都提升为int了
你字节sizeof(n_short+1)看看,4个字节了,你怎么就不听我的呢
还C++的bug
[/Quote]
----------
我知道啊。哦。终于明白了。 出丑了。终于明白了,怪不得
n_short=n_short就不会出现问题。原来它样做,就不会提升。谢谢大侠啊。
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 arong1234 的回复:]
long和int也应该如此
const long MAX_LONG = (((unsigned long)(~0))>>1);//如果你的long的最大值不等于这个,说明你设置就是错误的

long i = MAX_LONG;
i-1 应该是-MAX_LONG-1
0-1 = -1

int 也一样

当然unsigned 时没有符号位,自然就没有这样

总之你要学会逐位加减法,不懂这个,你就不会明白的,找本计算机原理讲数字在计算机里的表示的书看看

[/Quote]

不明白了。你的说法不不能说明了问题。同样的方法,用在三种类型变量上,得出了不同的计算方法。而这个计算方法只出现在cout对像中。short没有循环,而long和int都循环了。
ttkk_2007 2008-04-12
  • 打赏
  • 举报
回复
哥们,我不是跟你说了吗,已经提升了
(n_short + 1),一个short和int型相加,都提升为int了
你字节sizeof(n_short+1)看看,4个字节了,你怎么就不听我的呢
还C++的bug
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
我的分析如下: 在第一个程序代码中,采用了cout对像cout < < "\t\tn_short + 1: " < < (n_short + 1);
进行计算时,没有达到预期的结果,而在第二程序代码,通过n_short=n_short+1。进行计算达到预期的结果。
而同样的问题没有出现在int型和long中.我觉得是cout对像在计算short变量时发生了问题。是C++的BUG。
arong1234 2008-04-12
  • 打赏
  • 举报
回复
long和int也应该如此
const long MAX_LONG = (((unsigned long)(~0))>>1);//如果你的long的最大值不等于这个,说明你设置就是错误的

long i = MAX_LONG;
i-1 应该是-MAX_LONG-1
0-1 = -1

int 也一样

当然unsigned 时没有符号位,自然就没有这样

总之你要学会逐位加减法,不懂这个,你就不会明白的,找本计算机原理讲数字在计算机里的表示的书看看
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 arong1234 的回复:]
考虑位上的变化就明白了
signed short, 最大值是0x7FFF再加1后变为8000,这就是-32768
至于0-1,当然就变成了0xFFFF,也就是-1

[/Quote]
可是为什么int和long型。就不同了呢。再就是在第二个代码清单中,为什么又不同了呢。
arong1234 2008-04-12
  • 打赏
  • 举报
回复
考虑位上的变化就明白了
signed short, 最大值是0x7FFF再加1后变为8000,这就是-32768
至于0-1,当然就变成了0xFFFF,也就是-1
ttkk_2007 2008-04-12
  • 打赏
  • 举报
回复
那就是提升为int了
cout << "\t\tn_short + 1: " << sizeof((n_short + 1)); 你输出看看行了,已经是4个字节了
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
哦???没发现过这个问题,长见识了!呵呵!
n_short_unsigned=0后减1: 65535是正确的,
n_short最大值32767后加1: -32768
不明白了……
----------------------
C++编译就是这样,当一个整型变量超越了限制,其值就会从范围的另一端取值。使其超越限制是不出错。如
int型变量占用了4字节,取值范围为-2147483648~ 2147483647.如果int型变量加减运算。超过了2147483647。就会从头开始循环。如加1后就变成了-2147483648。加2就是-2147483647
  • 打赏
  • 举报
回复
哦???没发现过这个问题,长见识了!呵呵!
n_short_unsigned=0后减1: 65535是正确的,
n_short最大值32767后加1: -32768
不明白了……
jingzizhuo 2008-04-12
  • 打赏
  • 举报
回复
#include <iostream>
#include <climits>
using namespace std;

int main()
{
short n_short=SHRT_MAX;
unsigned short n_short_unsigned=0;
cout << "n_short= " << n_short;
n_short=n_short+1;
cout << "\nn_short size of " << sizeof(n_short) << " bytes.\n";
cout << "n_short最大值32767后加1: " << n_short << endl;
n_short_unsigned=n_short_unsigned-1;
cout << "n_short_unsigned=0后减1: " << n_short_unsigned;

return 0;
}
编译结果如下:
n_short= 32767
n_short size of 2 bytes.
n_short最大值32767后加1: -32768
n_short_unsigned=0后减1: 65535
==========================
请在看个代码,short型变量又能显示预测的结果。严重不明白了。
DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序包含了最新版的DirectX redist(Jun2010),并且全部DX文件都有Microsoft的数字签名,安全放心。 本程序为了应对一般电脑用户的使用,采用了傻瓜式一键设计,只要点击主界面上的“检测并修复”按钮,程序就会自动完成校验、检测、下载、修复以及注册的全部功能,无需用户的介入,大大降低了使用难度。 本程序适用于多个操作系统,如Windows XP(需先安装.NET 2.0,详情请参阅“致Windows XP用户.txt”文件)、Windows Vista、Windows 7、Windows 8、Windows Blue(Windows 8.1),同时兼容32位操作系统和64位操作系统。本程序会根据系统的不同,自动调整任务模式,无需用户进行设置。 本程序的V3.0版为标准版、增强版以及在线修复版。其的标准版以及增强版都包含完整的DirectX组件,增强版还额外包含了c++ Redistributable Package,因此增强版适合无法自行解决c++相关问题的用户使用;在线修复版的功能与标准版相同,只是其所需的文件将通过Internet下载,因此大大减小了程序的体积。本程序的各个版本之间,主程序完全相同,只是配套使用的数据包不同。因此,当您使用标准版数据包时,程序将进行标准修复;当您使用增强版的数据包时,程序将进行增强修复;当数据包不全或没有数据包(即只有DirectX Repair.exe程序)时,程序将进行在线修复。在线修复、离线修复可自由灵活组合,充满足不同用户的需要。 本程序自V2.0版起采用全新的底层程序架构,使用了异步多线程编程技术,使得检测、下载、修复单独进行,互不干扰,快速如飞。新程序更改了自我校验方式,因此使用新版本的程序时不会再出现自我校验失败的错误;但并非取消自我校验,因此程序安全性与之前版本相同,并未降低。 程序有自动更新c++功能。由于绝大多数软件运行时需要c++的支持,并且c++的异常也会导致0xc000007b错误,因此程序在检测修复的同时,也会根据需要更新系统c++组件。V3.0版本使用了全新的c++扩展包,可以大幅提高工业软件修复成功的概率。此功能仅限于增强版。 程序有两种窗口样式。正常模式即默认样式,适合绝大多数用户使用。另有一种简约模式,此时窗口将只显示最基本的内容,修复会自动进行,修复完成10秒钟后会自动退出。该窗口样式可以使修复工作得更简单快速,同时方便其他软件、游戏将本程序内嵌,即可进行无需人工参与的快速修复。开启简约模式的方法是:打开程序所在目录下的“Settings.ini”文件(如果没有可以自己创建),将其的“FormStyle”一项的值改为“Simple”并保存即可。 程序有高级筛选功能,开启该功能后用户可以自主选择要修复的文件,避免了其他不必要的修复工作。同时,也支持通过文件进行辅助筛选,只要在程序目录下建立“Filter.dat”文件,其的每一行写一个需要修复文件的序号即可。该功能仅针对高级用户使用,并且必须在正常窗口模式下才有效(简约模式时无效)。 本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时和查找原因,以便找到解决办法。 程序的“选项”对话框包含了3项高级功能。点击其的“注册系统文件夹所有dll文件”按钮可以自动注册系统文件夹下的所有dll文件。该项功能不仅能修复DirectX的问题,还可以修复系统很多其他由于dll未注册而产生的问题,颇为实用。点击该按钮旁边的小箭头,还可以注册任意指定文件夹下的dll文件,方便用户对绿色版、硬盘版的程序组件进行注册。点击第二个按钮可以为dll文件的右键菜单添“注册”和“卸载”项,方便对单独的dll文件进行注册。请注意,并不是所有的dll文件都可以通过这种方式注册。 新版程序集成了用户反馈程序,可以在用户允许的前提下发送检测修复结果。用户也可以在出现问题时通过反馈程序和软件作者进行交流,共同查找问题。反馈是完全自愿和匿名(如果不填写E-mail地址)的。 本程序的通用版基于Microsoft .NET Framework 2.0开发,对于Windows 2000、Windows XP、Windows 2003的用户需要首先安装.NET Framework 2.0或更高版本方可运行本程序。有关下载和安装的详细信息请参阅“致Windows XP用户.txt”文件。对于Windows Vista、Windows 7用户,可以直接运行本程序。 同时鉴于Windows 8(Windows Blue、Windows 8.1)系统默认未包含.NET Framework 2.0,因此新版的程序文件夹内将包含一个DirectX_Repair_win8的特别版程序,该程序功能与通用版相同,基于.NET Framework 4.0开发,可以在Windows8(Windows Blue、Windows 8.1)系统直接运行(其他系统如果安装了.NET Framework 4.0也可以运行这个特别版的程序)。 本程序的官方博客地址为:http://blog.csdn.net/vbcom/article/details/6962388所有的更新以及技术支持都可以到该博客上找到。
DirectX修复工具(DirectX Repair)是一款系统级工具软件,简便易用。本程序为绿色版,无需安装,可直接运行。 本程序的主要功能是检测当前系统的DirectX状态,如果发现异常则进行修复。程序主要针对0xc000007b问题设计,可以完美修复该问题。本程序包含了最新版的DirectX redist(Jun2010),并且全部DX文件都有Microsoft的数字签名,安全放心。 本程序为了应对一般电脑用户的使用,采用了傻瓜式一键设计,只要点击主界面上的“检测并修复”按钮,程序就会自动完成校验、检测、下载、修复以及注册的全部功能,无需用户的介入,大大降低了使用难度。 本程序适用于多个操作系统,如Windows XP(需先安装.NET 2.0,详情请参阅“致Windows XP用户.txt”文件)、Windows Vista、Windows 7、Windows 8、Windows 8.1、Windows 8.1 Update、Windows 10,同时兼容32位操作系统和64位操作系统。本程序会根据系统的不同,自动调整任务模式,无需用户进行设置。 本程序的V3.3版为标准版、增强版以及在线修复版。其的标准版以及增强版都包含完整的DirectX组件。除此之外,增强版还额外包含了c++ Redistributable Package,因此增强版不但能解决DirectX组件的问题,而且还能解决c++组件异常产生的问题。增强版适合无法自行解决c++相关问题的用户使用。在线修复版的功能与标准版相同,只是其所需的文件将通过Internet下载,因此大大减小了程序的体积。本程序的各个版本之间,主程序完全相同,只是配套使用的数据包不同。因此,当您使用标准版数据包时,程序将进行标准修复;当您使用增强版的数据包时,程序将进行增强修复;当数据包不全或没有数据包(即只有DirectX Repair.exe程序)时,程序将进行在线修复。在线修复、离线修复可自由灵活组合,充满足不同用户的需要。 本程序自V2.0版起采用全新的底层程序架构,使用了异步多线程编程技术,使得检测、下载、修复单独进行,互不干扰,快速如飞。新程序更改了自我校验方式,因此使用新版本的程序时不会再出现自我校验失败的错误;但并非取消自我校验,因此程序安全性与之前版本相同,并未降低。 程序有自动更新c++功能。由于绝大多数软件运行时需要c++的支持,并且c++的异常也会导致0xc000007b错误,因此程序在检测修复的同时,也会根据需要更新系统c++组件。自V3.2版本开始使用了全新的c++扩展包,可以大幅提高工业软件修复成功的概率。修复c++的功能仅限于增强版,标准版及在线修复版在系统c++异常时(非丢失时)会提示用户使用增强版进行修复。 程序有两种窗口样式。正常模式即默认样式,适合绝大多数用户使用。另有一种简约模式,此时窗口将只显示最基本的内容,修复会自动进行,修复完成10秒钟后会自动退出。该窗口样式可以使修复工作得更简单快速,同时方便其他软件、游戏将本程序内嵌,即可进行无需人工参与的快速修复。开启简约模式的方法是:打开程序所在目录下的“Settings.ini”文件(如果没有可以自己创建),将其的“FormStyle”一项的值改为“Simple”并保存即可。 程序有高级筛选功能,开启该功能后用户可以自主选择要修复的文件,避免了其他不必要的修复工作。同时,也支持通过文件进行辅助筛选,只要在程序目录下建立“Filter.dat”文件,其的每一行写一个需要修复文件的序号即可。该功能仅针对高级用户使用,并且必须在正常窗口模式下才有效(简约模式时无效)。 本程序有自动记录日志功能,可以记录每一次检测修复结果,方便在出现问题时,及时和查找原因,以便找到解决办法。 程序的“选项”对话框包含了4项高级功能。点击其的“注册系统文件夹所有dll文件”按钮可以自动注册系统文件夹下的所有dll文件。该项功能不仅能修复DirectX的问题,还可以修复系统很多其他由于dll未注册而产生的问题,颇为实用。点击该按钮旁边的小箭头,还可以注册任意指定文件夹下的dll文件,方便用户对绿色版、硬盘版的程序组件进行注册。点击第二个按钮可以为dll文件的右键菜单添“注册”和“卸载”项,方便对单独的dll文件进行注册。请注意,并不是所有的dll文件都可以通过这种方式注册。点击“DirectX版本”选项卡可以自行修改系统DirectX的版本信息。点击“DirectX速”选项卡可以控制系统DirectX速的开启与关闭。 新版程序集成了用户反馈程序,可以在用户允许的前提下发送检测修复结果。用户也可以在出现问题时通过反馈程序和软件作者进行交流,共同查找问题。反馈是完全自愿和匿名(如果不填写E-mail地址)的。 本程序的通用版基于Microsoft .NET Framework 2.0开发,对于Windows 2000、Windows XP、Windows 2003的用户需要首先安装.NET Framework 2.0或更高版本方可运行本程序。有关下载和安装的详细信息请参阅“致Windows XP用户.txt”文件。对于Windows Vista、Windows 7及后续用户,可以直接运行本程序。 同时鉴于Windows 8(Windows 8.1、Windows 8.1 Update)、Windows 10系统默认未包含.NET Framework 2.0,因此新版的程序文件夹内将包含一个DirectX_Repair_win8的特别版程序,该程序功能与通用版相同,基于.NET Framework 4.0开发,可以在Windows8(Windows 8.1、Windows 8.1 Update)、Windows 10系统直接运行(其他系统如果安装了.NET Framework 4.0也可以运行这个特别版的程序)。 本程序的官方博客地址为:http://blog.csdn.net/vbcom/article/details/6962388 所有的更新以及技术支持都可以到该博客上找到。

65,207

社区成员

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

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