注册 登录
编程论坛 C语言论坛

两个一样的代码输出的结果为何不同 求大佬指点迷津

下凡小仙男 发布于 2020-03-18 18:11, 5063 次点击
#include<stdio.h>
int main(void)
{
    unsigned int a;
    while (a>0)
    a++;
    printf("unsign_int max %u\n",a-1);
    return 0;
}
输出的结果是正确答案
下面的代码却是一直在变化最大值一直递增不停又或者是什么都没有
#include<stdio.h>
int main(void)
{
    unsigned int a=1;
    while (a>0)
        a++;
    printf("unsigned_int max=%u\n",a-1);   
    return 0;
 
}
33 回复
#2
下凡小仙男2020-03-18 18:13
回复 楼主 下凡小仙男
我把开头的a=1;这有什么影响
#3
下凡小仙男2020-03-18 18:15
回复 楼主 下凡小仙男
定义成a=0 答案又出来了
#4
lin51616782020-03-18 18:25
代码写的不一样 输出就不一样
有什么奇怪的?
#5
rjsp2020-03-18 18:27
第一段代码 a 未赋值就读取了,属于未定义行为,虽然一般也会有正确答案。
第二段代码是正确的,你的描述——“一直在变化最大值一直递增不停又或者是什么都没有”——我却听不懂。

此外,
while (a>0)
        a++;
不就是 a = 0; 吗?!
#6
下凡小仙男2020-03-18 19:12
回复 4楼 lin5161678
...
#7
下凡小仙男2020-03-18 19:12
回复 5楼 rjsp
就是我第二段代码输出不了任何东西,不知道为什么
#8
下凡小仙男2020-03-18 19:16
回复 7楼 下凡小仙男
不好意思,是我还没等计算机算出来就把程序叉掉了
#9
叶纤2020-03-18 19:18
看来楼主对于未定义和未初始化并不怎么熟悉
    初始化=在定义时为对象提供了一个已知值。
     分配=给对象赋予超出定义点的已知值。
     未初始化=该对象尚未获得已知值。
现在是一代码并没有初始化,直接使用那是做死行为,
二代码初始化了,也定义了,不过因为是死循环,显示到类型的最大值,不过呢我的电脑怎么是32位的我才刚知道
#10
return_02020-03-18 19:21
运行超时挺常见的,可能是IDE的问题
#11
Sv少2020-03-18 19:22
你调试一下 看一下a的值
第一段a 没有初始值 有的直接可能默认为0;直接跳过循环,有输出值。
第二段a=1 而a++ 使得a>0条件成立  就会在while中一直循环,不会执行下面语句,没有输出。
#12
下凡小仙男2020-03-18 19:23
回复 9楼 叶纤
,a到了最大的时候继续a++,他就会成负数,我之后printf输出的是a-1,他就会成最大数了。是不是这样考虑的
#13
return_02020-03-18 19:27
你每次输出值就能看出来了。
#14
下凡小仙男2020-03-18 19:27
回复 11楼 Sv少
a到了最大的时候继续a++,他就会成负数,我之后printf输出的是a-1,他就会成最大数了。会不会是这样考虑的
#15
return_02020-03-18 19:29
第二个是死循环
#16
return_02020-03-18 19:30
回复 14楼 下凡小仙男
你把a定义成0他就不满足a>0的条件,就会跳过死循环,
#17
下凡小仙男2020-03-18 19:33
回复 16楼 return_0
我把a定义成0,马上就出结果,要是定义成1,程序要等一会儿才出结果,很好奇其中的秘密
#18
rjsp2020-03-18 19:50
以下是引用下凡小仙男在2020-3-18 19:33:52的发言:

我把a定义成0,马上就出结果,要是定义成1,程序要等一会儿才出结果,很好奇其中的秘密
什么秘密?
#19
叶纤2020-03-18 20:05
避免使用无符号类型,因为使用无符号进行运算有可能会出现环绕和益处,就比如你第二个代码,如果益处就会进入环绕状态,也就是说最后是1-1=0,0不大于0为faulse,此时终止循环,楼主又说了把a定义为0,那就直接faulse,然后直接a-1为复数,此时进行了环绕为最大值
#20
叶纤2020-03-18 20:10
总之除非必要使用无符号的情况下应避免使用
#21
下凡小仙男2020-03-18 22:06
回复 18楼 rjsp
就是两者之间为什么速度会不一样
#22
下凡小仙男2020-03-18 22:06
回复 19楼 叶纤
就是unsigned 少用吗 我今天看视频学到了这个就用了下哈哈哈
#23
hbccc2020-03-18 22:39
第一个程序,由于a未赋值,运行时这个值时计算机随机给的,大概率时0,然后不会执行循环,只执行循环后面的printf语句,无符号数0减去1,就变成了最大值。
第二个程序,a赋值了1,就可以进行循环了,但while后只有a++,所以a就不停的自增,进入死循环,但a自增到最大值时,变为0,就可以跳出循环,这时执行printf,还是0-1,变成最大值。

[此贴子已经被作者于2020-3-18 22:41编辑过]

#24
下凡小仙男2020-03-19 16:51
回复 23楼 hbccc
#25
rjsp2020-03-19 18:14
以下是引用下凡小仙男在2020-3-18 22:06:03的发言:

就是两者之间为什么速度会不一样

因为你正确的代码是从1走到最大值,而错误的代码可能是从中间的垃圾值走到最大值。
前者路程远,当然耗时久。

而对于 无符号整型 和 具符号整型 的选择,C/C++的标准库中都是优先选用无符号整型。
因为前者在不需要表示负数的场合下,可以比后者表示的范围更大,那就不容易溢出。
在大部分CPU上,前者运算效率也高于后者。
更主要的是,具符号整型的溢出 属于 未定义行为
#26
叶纤2020-03-19 19:28
以下是引用下凡小仙男在2020-3-18 22:06:59的发言:

就是unsigned 少用吗 我今天看视频学到了这个就用了下哈哈哈

无符号类型有它的优点,但是无符号类型也存在陷阱,所以并不是让你完全禁止使用,而是除非在特殊情况下或不可避免,否则请避免使用无符号数字
1 那么使用无符号数字在哪里合理呢?
   
首先,在进行位操作时,首选无符号数字
其次,在某些情况下仍然不可避免地要使用无符号数,主要是那些与数组索引有关的数字。
另请注意,如果您是为嵌入式系统(例如Arduino)或其他处理器/内存受限的环境而开发的,出于性能方面的考虑,无符号数的使用更为常见并被接受(在某些情况下是不可避免的)。
2 为什么说避免使用
    当不需要负数时,无符号整数非常适合于网络和内存很少的系统,因为无符号整数可以存储更多的正数而不会占用额外的内存。
无符号整数不会溢出。 取而代之的是,如果值超出范围,则将其除以该类型的最大数除以一,然后仅保留其余部分。也就是回绕
举个例子     数字280太大,无法容纳0到255的1字节范围。大于类型的最大数字的1是256。因此,我们将280除以256,得到1个余数24。24的余数 被储存了。
程序代码:
        #include <iostream>
     
    int main()
    {
        unsigned short x{ 65535 }; // largest 16-bit unsigned value 2*8。 16possible
        std::cout << "x was: " << x << '\n';
     
        x = 65536; // 65536 is out of our range, so we get wrap-around65536超出了我们的范围,因此我们得到了环绕
        std::cout << "x is now: " << x << '\n';0
     
        x = 65537; // 65537 is out of our range, so we get wrap-around65537超出了我们的范围,因此我们得到了环绕。    1
        std::cout << "x is now: " << x << '\n';
     
        return 0;
    }

程序代码:

    避免使用无符号
    #include <iostream>
     
    int main()
    {
    unsigned int x{ 3 };
    unsigned int y{ 5 };
     
    std::cout << x - y << '\n';
    return 0;
    }



    发生这种情况的原因是-2环绕到一个数字,该数字接近4字节整数范围的顶部。 当使用-运算符反复减小无符号整数时,通常会发生不必要的回绕。 引入循环后,您将看到一个示例。
    •  第二,混合有符号和无符号整数时,可能会导致意外行为。 在上面的示例中,即使其中一个操作数(x或y)是有符号的,另一个操作数(无符号的一个)也将导致有符号的一个被提升为无符号的整数,并且将产生相同的行为!
    • 除非在特殊情况下或不可避免,否则请避免使用无符号数字。
当然以上内容是我的学习笔记,有很多地方都不明白,如果对
无符号是陷阱还有疑问的话,请参阅http://soundsoftware.ac.uk/c-pitfall-unsigned.html
#27
lin51616782020-03-20 01:10
回复 26楼 叶纤
无符号类型的确有一些容易出错的地方
但是你提到的根本不是无符号类型的问题
甚至是无符号类型的优点
有符号类型一样会出现溢出
并且有符号类型溢出是未定义行为
有可能回绕 有可能出现意料之外的情况
无符号类型溢出保证是回绕
是一个可以作为功能利用的机制
有符号类型溢出则不能作为功能利用
#28
叶纤2020-03-20 11:01
回复 27楼 lin5161678
我已经把几大主题分的清清楚楚,如果看不懂请尝试完整的看一遍,如果看不懂c++代码,那你可以回炉了
#29
lin51616782020-03-20 11:14
回复 28楼 叶纤
我看得懂你写的 你看不懂我写的
适合回炉的人显然是你才对
数字280太大,无法容纳0到255的1字节范围。大于类型的最大数字的1是256。因此,我们将280除以256,得到1个余数24。24的余数 被储存了。

然后呢 这个和无符号有什么关系
你用signed char ch = 280;
有符号不也一样结果24
那么问题来了
为什么 无符号类型 溢出结果24是缺点?
有符号类型 溢出结果24就不是缺点了??
牵强附会

只有本站会员才能查看附件,请 登录


[此贴子已经被作者于2020-3-20 11:17编辑过]

#30
叶纤2020-03-20 11:32
回复 29楼 lin5161678
我全文没提过一次缺点二字,你在哪里看到的缺点?陷阱并非缺点,请不要强词夺理,避免并非禁止,请不要脑补内容
#31
叶纤2020-03-20 11:35
对于无理取闹的行为回复一次表示尊重,以后就是无视
#32
lin51616782020-03-20 11:52
以下是引用叶纤在2020-3-20 11:32:06的发言:

我全文没提过一次缺点二字,你在哪里看到的缺点?陷阱并非缺点,请不要强词夺理,避免并非禁止,请不要脑补内容

你说要避免使用
理由是无符号数会回绕
并给出一个例子 (unsigned char)280 结果是 24
所以要避免

问题是 按照这个例子 使用有符号数 效果完全一样是 24
为什么无符号类型就需要避免使用 而有符号数就不需要避免使用了?



#33
lin51616782020-03-20 11:53
回复 31楼 叶纤
对于一知半解 牵强附会的解答
纠正多少次都义不容辞
#34
下凡小仙男2020-03-22 11:49
回复 26楼 叶纤
谢谢大佬,虽然我现在还看不懂哈哈哈
1