为什么使用int的值i;未定义的行为,但使用rand()的值不是

Why is using the value of int i; undefined behaviour but using the value of rand() is not?

本文关键字:rand 的值 int 为什么 未定义      更新时间:2023-10-16

如果我不初始化i,我不知道它的值,但我也无法预测rand()的值。

但另一方面,我知道未初始化的i的值在INT_MININT_MAX之间,我也知道rand()的值在0RAND_MAX之间。

为什么使用未初始化的i的值未定义行为,但使用rand()的值不是?

未初始化变量的值为undefinedrand()的返回值为,定义为给定种子的伪随机序列中的下一个数字。

您可以依赖rand()返回一个伪随机数。您不能依赖未初始化的int i的值的任何特征。

我查阅了C99标准(ISO/IEC 9899:1999),这是我唯一可用的标准文件,但我严重怀疑这些事情已经改变了。在6.2.6类型的表示一章中,说明了整数可以用填充位存储在内存中,填充位的值未指定,但可以包含奇偶校验位,这将在初始化和对整数进行任何算术操作时设置。某些表示(例如奇偶校验不匹配)可能是陷阱表示,其行为未定义(但可能会终止您的程序)。

所以,不,你甚至不能指望一个未初始化的int iINT_MIN <= i <= INT_MAX

标准规定从未初始化的变量中读取是未定义的行为,所以它是。不能说它在INT_MININT_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