繁体   English   中英

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

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

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

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

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

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

您可以依赖 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的值。

rand使用算法生成您的号码。 因此rand不是未定义的,如果你使用srand开始随机生成你选择一个像42这样的值,你每次启动应用程序时都会得到相同的值尝试启动这个例子你会看到:

#include <stdio.h>
#include <stdlib.h>

int main()
{
  srand(42);

  printf("%d\n", rand());
  return 0;
}

另见: https//en.wikipedia.org/wiki/List_of_random_number_generators

考虑以下代码中的变量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之后从未使用过,因此编译器可以使用相同的寄存器来保持x已用于保持q 确保函数总是返回值0-65535将需要添加一些额外的指令,而不是简单地让它返回分配给x的寄存器中发生的任何事情。

请注意,从标准作者的角度来看,如果标准不要求编译器使x保持0-65535之间的值,那么如果代码试图使用,它也可能没有指定任何可能发生的事情。 x 希望在这种情况下提供任何行为保证的实现可以自由地执行,但标准没有要求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM