遇到问题的情景:在学习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
所以 -- 其实是这样赋值的:
给定一个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数组;