小朋友学C语言(25):两数交换

(一)

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 5;
    printf("Before swap: a = %d, b = %d\n", a, b);
    int temp = a;
    a = b;
    b = temp;
    printf("After swap: a = %d, b = %d\n", a, b);
    return 0;
}

运行结果:

Before swap: a = 10, b = 5
After swap: a = 5, b = 10

分析:temp = a,这里等号表示赋值。左边的temp表示变量,右边的a表示a的值。 只能把一个常量(a的值)赋值给变量(temp)。 不要理解成是把变量a赋值给变量temp。因为变量不能赋值给变量。 temp = a,得到temp = 10 a = b,得到a = 5 b = temp,得到 b = 10

(二)

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 5;
    printf("Before swap: a = %d, b = %d\n", a, b);
    a ^= b;
    b ^= a;
    a ^= b;
    printf("After swap: a = %d, b = %d\n", a, b);
    return 0;
}

运行结果:

Before swap: a = 10, b = 5
After swap: a = 5, b = 10

分析:请用笔和纸计算下面三个式子的值 a ^= b(等价于a = a ^ b。表示先求a和b的异或结果,再把结果赋值给a。) b ^= a(等价于b = b ^ a) a ^= b(等价于a = a ^ b)

(三)

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 5;
    printf("Before swap: a = %d, b = %d\n", a, b);
    a = a + b;
    b = a - b;
    a = a - b;
    printf("After swap: a = %d, b = %d\n", a, b);
    return 0;
}

运行结果:

Before swap: a = 10, b = 5
After swap: a = 5, b = 10

分析:请口算或用纸笔计算下面三个式子: a = a + b; b = a - b; a = a - b;

(四)注意

如果数很大的话,采用(三)中的方法,a = a + b这一步,有可能发出内存溢出现象

#include <stdio.h>
int main()
{
    int a = 2147483647;
    int b = 1;
    printf("Before swap: a = %d, b = %d\n", a, b);
    a = a + b;
    printf("After addition: a = %d\n", a);
    b = a - b;
    a = a - b;
    printf("After swap: a = %d, b = %d\n", a, b);
    return 0;
}

运行结果:

Before swap: a = 2147483647, b = 1
After addition: a = -2147483648
After swap: a = 1, b = 2147483647

这里a + b得到的竟然是一个负数!这是什么回事呢? 这跟整型的取值范围有关。int类型占4个字节,也就是32位。 最左边那位为符号,0代表正号,1代表负号。

二进制

十进制

00000000,00000000,00000000,00000001

1

10000000,00000000,00000000,00000001

-1

01111111,11111111,11111111,11111111

2147483647

1111111,11111111,11111111,11111111

-2147483647

00000000,00000000,00000000,00000000

0

10000000,00000000,00000000,00000000

这是多少呢?

这里10000000,00000000,00000000,00000000相当于十进制的多少呢?是-0吗? 如果是-0的话,因为0无所谓正负,-0就是0,这会导致计算机里面有两种方式表示0。这是不允许的。那么这个数到底表示多少呢? 事实上,这个数很特殊。最左边的1不仅表示负号,还参与了运算

  10000000,00000000,00000000,00000000 = - 2 ^ 31 = - 2147483648 这样,程序中a = a + b得到了负数就好理解了。 接下来因为减掉之后,数变小了,又变回正常的正数了。

从这里可以看出,int类型的取值范围为[-2147483648, 2147483647], 即[-2^31, 2^31-1]

(五)结论

(1)使用(三)中的方法交换两数后,如果数很大的话 ,中间a = a + b有可能得到错误的值,但最终的结果是正确的。 (2)如果数很大的话,比如a = 2147483647; b = 1;a = a + b的期望结果是214748364,但是因为这个数不在int的取值范围内,所以得到了一个负数。这个叫做内存溢出(可联想为:米缸装满了,再也装不进去,继续装的话,米就会溢出来了)。 内存溢出是一种程序漏洞,有可能被黑客所利用并攻击(可联想为:米被老鼠吃了)。 所以,建议不要使用(三)中的方法来交换两个数。

原文发布于微信公众号 - 海天一树(gh_de7b45c40e8b)

原文发表时间:2017-11-20

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏决胜机器学习

有趣的算法(七) ——快速排序改进算法

有趣的算法(七) ——快速排序改进算法 (原创内容,转载请注明来源,谢谢) 一、概述 快速排序,被认为是最好的排序算法之一。快速排序是20世纪60年代被提出...

33140
来自专栏开发技术

排序之希尔排序(shell sort)

本篇博客是在伍迷兄的博客基础上进行的,其博客地址点击就可以进去,里面好博客很多,我的排序算法都来自于此;一些数据结构方面的概念我就不多阐述了,伍迷兄的博客中都...

14430
来自专栏小筱月

各种排序算法

冒泡排序还有一种优化算法,就是立一个flag,当在一趟序列遍历中元素没有发生交换,则证明该序列已经有序

16830
来自专栏C语言及其他语言

[每日一题]统计字符

这也是一道字符串类型中比较常规的题(但含自定义函数哦),但前提得知道一个函数哦,就会简单很多!!! 如果你不知道,写完这题你就知道了哦!!! 题目描述 编写一...

37480
来自专栏Python小屋

Python内置函数iter()语法及应用

iter()函数用来返回指定对象的迭代器,有两种用法:iter(iterable)和iter(callable, sentinel),前者要求参数必须为序列或者...

38460
来自专栏数据小魔方

左右用R右手Python系列——字符串格式化输出

学习Python不到一个月,虽然学的很渣,但是还是想通过这种途径分享自己的学习心得,毕竟当初学习R语言也是这么走过来的。 今天是R语言与Python综合系列的第...

44860
来自专栏Java编程

四道Java基础题,你能对几道?

如果这道题你能得出正确答案,并能了解其中的原理的话。说明你基础还可以。如果你的答案 是 true 和true的话,你的基础就有所欠缺了。

1.1K10
来自专栏彭湖湾的编程世界

【算法】哈希表的诞生

《算法(java)》                           — — Robert Sedgewick, Kevin Wayne

16170
来自专栏彭湖湾的编程世界

【算法】哈希表的诞生

参考资料 《算法(java)》                           — — Robert Sedgewick, Kevin Wayne 《数据结...

358100
来自专栏云霄雨霁

排序----希尔排序

16500

扫码关注云+社区

领取腾讯云代金券