如果我不初始化i
,我不知道它的值,但我也无法预测rand()
的值。
但另一方面,我知道未初始化的i
的值在INT_MIN
和INT_MAX
之间,我也知道rand()
的值在0
和RAND_MAX
之间。
为什么使用未初始化的i
的值未定义行为,但使用rand()
的值不是?
未初始化变量的值为undefined。rand()
的返回值为,定义为给定种子的伪随机序列中的下一个数字。
您可以依赖于rand()
返回一个伪随机数。您不能依赖未初始化的int i
的值的任何特征。
我查阅了C99标准(ISO/IEC 9899:1999),这是我唯一可用的标准文件,但我严重怀疑这些事情已经改变了。在6.2.6类型的表示一章中,说明了整数可以用填充位存储在内存中,填充位的值未指定,但可以包含奇偶校验位,这将在初始化和对整数进行任何算术操作时设置。某些表示(例如奇偶校验不匹配)可能是陷阱表示,其行为未定义(但可能会终止您的程序)。
所以,不,你甚至不能指望一个未初始化的int i
是INT_MIN
<= i
<= INT_MAX
标准规定从未初始化的变量中读取是未定义的行为,所以它是。不能说它在INT_MIN
和INT_MAX
之间。事实上,不能认为这个变量有任何值,所以你甚至不能检验假设*。
rand()
被设计为在一个范围内产生一个随机数。如果从rand()
的结果中读取是未定义的,它将不属于任何库的一部分,因为它不能被使用。
*通常"未定义行为"提供了优化的范围。优化器可以对未初始化的变量做任何事情,假设它不是从。
定义rand
的值为(伪)随机。未初始化变量的值没有定义为任何值。这就是区别,无论什么东西被定义为有意义的东西(而rand()
也是有意义的-它给出了(伪)随机数)或未定义。
简短的回答,就像其他人说的,是因为标准是这么说的。
访问未初始化的变量值的行为(在标准中描述为执行左值到右值的转换)会产生未定义的行为。
rand()
被指定为给定0到RAND_MAX
之间的值,其中RAND_MAX
(在c++的<cstdlib>
和C的<stdlib.h>
中声明的宏)被指定为具有至少32767
的值。
考虑以下代码中的变量x
:
uint32_t blah(uint32_t q, uint32_t r)
{
uint16_t x;
if (q)
x=foo(q); // Assume return type of foo() is uint16_t
if (r)
x=bar(r); // Assume return type of bar() is uint16_t
return x;
}
由于代码永远不会给x
分配0-65535范围之外的值,32位处理器的编译器可以合法地为它分配一个32位寄存器。实际上,由于q
的值在第一次写入x
之后永远不会被使用,编译器可以使用与q
相同的寄存器来保存x
。与简单地让它返回分配给x
的寄存器中的任何内容相比,确保函数总是返回值0-65535需要添加一些额外的指令。
注意,从标准作者的角度来看,如果标准不要求编译器使x
保持0-65535之间的值,那么也可以不指定任何关于代码试图使用x
时可能发生的情况。希望在这种情况下提供任何行为保证的实现可以自由地这样做,但是标准没有强加任何要求。
rand
使用算法生成您的号码。所以rand
不是未定义的,如果当你使用srand
开始随机生成时,你选择一个像42这样的值,你每次启动你的应用程序时都会得到相同的值尝试启动这个示例,您将看到:
#include <stdio.h>
#include <stdlib.h>
int main()
{
srand(42);
printf("%dn", rand());
return 0;
}
参见:https://en.wikipedia.org/wiki/List_of_random_number_generators