笔记29:关于设置无穷大为【#define INF 0x3f3f3f3f】的原因

遇到问题的情景:在学习Dijstra算法时遇到了以下代码

#define INF 0x3f3f3f3f

int map[10]; //数组
memset(map, INF, sizeof(map));

因此产生了疑问:为何要把无穷大设置为0x3f3f3f3f这样一个奇怪的数字

a

a

a

a

a

解释:

a

(1)关于【0x 7f ff ff ff】和【0x 3f 3f 3f 3f】的区别:

函数memset()的声明为:

void *memset(void *str, int c, size_t n)

他的第二个参数的类型是int,即有符号整数(最高位是0代表正数,最高位是1代表负数),而int类型的数据占据内存的大小是4个字节;

因此int类型的最大值是:

(2进制)01111111;11111111;11111111;11111111

(10进制)2,147,483,647

(16进制)0x 7f ff ff ff

而0x3f3f3f3f对应的int类型值是:

(2进制)00111111;00111111;00111111;00111111

(10进制)1,061,109,567

(16进制)0x 3f 3f 3f 3f

a

a

a

a

 (2)memset()函数的赋值原理:

我们要首先注意一点,memset()函数的文档为:

通过函数的声明我们得知,要被赋给内存空间的值c是int类型,他占据空间大小为4个字节,但是后面给出的n代表的是要赋值给几个字节;这就出现了矛盾,memset函数是一个一个字节进行赋值的,但是函数中给定的值是int类型,一个int占据4字节,肯定不能在1个字节大小的内存空间中塞进去4字节大小的int数据;

a

a

所以 -- 其实是这样赋值的:

memset的用法详解 - 知乎

给定一个4字节大小的int类型数据c:[][][][][][][][] ; [][][][][][][][] ; [][][][][][][][] ; [][][][][][][][] ,在使用memset函数对内存空间的某一个字节进行赋值时,因为int数据占4个字节,所以塞不到1个字节空间中,因此函数memset会将数据c的最低8位赋值给那个内存中的字节里;

a

a

举例:

a

a

a

a

(3)为什么要把无穷大定义为【0x 3f 3f 3f 3f】而不是【0x 7f ff ff ff】:

INF=0x3f3f3f3f是 什么意思?_AEP_WYK的博客-CSDN博客

总结一下:一共4个原因

1.因为 0x3f3f3f3f 他的十进制数字和 0x7fffffff 一样,数量级都是10的9次方级,都足够大可以当作无穷大使用

2.无穷大的性质有俩【第一:无穷大+无穷大=无穷大】【第二:无穷大+随便一个有限的数=无穷大】,但是【对于第一条:如果使用0x7fffffff作为无穷大,那么俩0x7fffffff相加会造成int数据类型的溢出,从而导致变成负数】【对于第二条:和上一条的原因一样,0x7fffffff随便加一个数字都会造成int数据的溢出】,所以为了适配无穷大的这两条性质,将0x3f3f3f3f作为无穷大更合适

3.对于最短路径算法Dijstra算法,他会在判断中有语句【if (dis[u]+w[u][v]<dis[v])  dis[v]=dis[u]+w[u][v]】,很明显如果把无穷大设置为0x7fffffff那么这个加法会导致int数据类型溢出

4. 还有个原因跟memset()函数的赋值方式有关,如下的原因4

a

a

a

a

(4)原因4:


为什么定义INF为0x3F3F3F3F - 数据结构与算法 - 程序员的自我修养

 

【memset(map, 0x3f, sizeof(map))】:数组中都是1,061,109,567(16进制就是0x3f3f3f3f)

【memset(map, 0x3f3f3f3f, sizeof(map))】:数组中都是1,061,109,567

【memset(map, 0x7fffffff, sizeof(map))】:数组中都是-1

所以说我们想把map数组中的所有int值都设置为无穷大,那么如果用0x7fffffff进行设置,那就不能使用函数memset()了,因为函数memset是一个一个字节赋值的,而我们必须对四个字节一次性赋值【map[0]=0x7fffffff】才行;因为只有这样才能实现我们的数组map中所有的int数据类型元素都是无穷大值0x7fffffff,而不是-1;

所以说我们想把map数组中的所有int值都设置为无穷大,那么如果用0x3f3f3f3f进行设置,而0x3f3f3f3f的第一个字节就是0x3f,所以程序【memset(map, 0x3f, sizeof(map))】和【memset(map, 0x3f3f3f3f, sizeof(map))】的作用完全相同;数组中的int数值都是0x3f3f3f3f,即我们需要的无穷大值;

这样一来,我们通过程序【memset(map, 0x3f, sizeof(map))】或【memset(map, 0x3f3f3f3f, sizeof(map))】都可以得到,map数组中的每个int数据都是0x3f3f3f3f,也就是我们想要的无穷大!这样就很方便,因为程序【memset(map, 0x3f3f3f3f, sizeof(map))】看起来就像是直接把0x3f3f3f3f这4个字节的值直接赋值给了map数组;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值