[英]Why is using the value of int i; undefined behaviour but using the value of rand() is not?
If I don't initialise i
, I don't know its value, but also I cannot predict the value of rand()
. 如果我没有初始化
i
,我不知道它的价值,但我也无法预测rand()
的值。
But on the other hand, I know the value of the uninitialised i
is between INT_MIN
and INT_MAX
, also I know the value of rand()
is between 0
and RAND_MAX
. 但另一方面,我知道未初始化的
i
值在INT_MIN
和INT_MAX
之间,我也知道rand()
值介于0
和RAND_MAX
之间。
Why is using the value of the uninitialised i
undefined behaviour but using the value of rand()
is not? 为什么使用未初始化的值,
i
不确定的行为,但使用的值rand()
是不是?
The value of an uninitialized variable is undefined . 未初始化变量的值未定义 。 The return value of
rand()
is well-defined as being the next number in the pseudo-random sequence for the given seed . rand()
的返回值被明确定义为给定种子的伪随机序列中的下一个数字 。
You can rely on rand()
returning a pseudorandom number. 您可以依赖
rand()
返回伪随机数。 You cannot rely on any characteristic of the value of an uninitialized int i
. 您不能依赖未初始化的
int i
的值的任何特征。
I looked up the C99 standard (ISO/IEC 9899:1999), which is the only standard document I have available, but I seriously doubt these things have changed. 我查阅了C99标准(ISO / IEC 9899:1999),这是我唯一可用的标准文件,但我很怀疑这些事情已经发生了变化。 In chapter 6.2.6 Representations of types , it is stated that integers are allowed to be stored in memory with padding bits , the value of which is unspecified but may include parity bits, which would be set upon initialization and any arithmetic operation on the integer.
在第6.2.6章类型的表示中,声明允许整数存储在存储器中,填充位的值未指定,但可能包括奇偶校验位,它将在初始化时设置,并对整数进行任何算术运算。 Certain representations (like eg a parity mismatch) could be trap representations , the behaviour of which is undefined (but might well terminate your program).
某些表示(例如奇偶校验不匹配)可能是陷阱表示 ,其行为未定义 (但可能会终止您的程序)。
So, no, you cannot even rely on an uninitialized int i
to be INT_MIN
<= i
<= INT_MAX
. 所以, 不,你甚至不能依赖未初始化的
int i
为INT_MIN
<= i
<= INT_MAX
。
The standard says reading from an uninitialized variable is undefined behaviour, so it is. 标准说从未初始化的变量读取是未定义的行为,所以它是。 You cannot say that it is between
INT_MIN
and INT_MAX
. 你不能说它介于
INT_MIN
和INT_MAX
之间。 In fact, cannot really think of that variable as holding any value, so you couldn't even check that hypothesis * . 事实上,无法将该变量视为保留任何值,因此您甚至无法检查该假设* 。
rand()
on the other hand is designed to produce a random number within a range. 另一方面,
rand()
旨在生成一个范围内的随机数。 If reading from the result of rand()
were undefined, it wouldn't be part of any library because it couldn't be used. 如果从
rand()
的结果中读取未定义,则它不会是任何库的一部分,因为它无法使用。
* Usually "undefined behaviour" provides scope for optimization. *通常“未定义的行为”提供优化的范围。 The optimizer can do whatever it wants with an uninitialized variable, working under the assumption that it isn't read from.
优化器可以使用未初始化的变量执行任何操作,并假设它不是从中读取的。
Value of rand
is defined to be (pseudo-)random. rand
值被定义为(伪)随机的。 Value of an uninitialized variable is not defined to be anything. 未初始化变量的值未定义为任何值。 That is the difference, whether something is defined to be anything meaningful (while
rand()
is also meaningful - it gives (pseudo-)random numbers) or undefined. 这就是区别,无论某事被定义为有意义的东西(而
rand()
也是有意义的 - 它给出(伪)随机数)或未定义。
The short answer, like others have said, is because the standard says so. 与其他人一样,简短的回答是因为标准这样说。
The act of accessing the value of a variable (described in the standard as performing an lvalue to rvalue conversion) that is uninitialised gives undefined behaviour. 访问未初始化的变量值(在标准中描述为执行左值转换的左值)的行为给出了未定义的行为。
rand()
is specified as giving a value between 0 and RAND_MAX
, where RAND_MAX
(a macro declared in <cstdlib>
for C++, and <stdlib.h>
for C) is specified as having a value which is at least 32767
. rand()
被指定为给出0到RAND_MAX
之间的值,其中RAND_MAX
(在C ++的<cstdlib>
声明的宏,C的<stdlib.h>
)被指定为具有至少32767
的值。
rand
uses an algorithm to generate your number. rand
使用算法生成您的号码。 So rand
is not undefined and if when you use srand
to start the random generation you choose a value like 42, you will always get the same value each time you launch your app try to launch this example you will see: 因此
rand
不是未定义的,如果你使用srand
开始随机生成你选择一个像42这样的值,你每次启动应用程序时都会得到相同的值尝试启动这个例子你会看到:
#include <stdio.h>
#include <stdlib.h>
int main()
{
srand(42);
printf("%d\n", rand());
return 0;
}
see also: https://en.wikipedia.org/wiki/List_of_random_number_generators 另见: https : //en.wikipedia.org/wiki/List_of_random_number_generators
Consider variable x
in the following code: 考虑以下代码中的变量
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;
}
Since code never assigns x
a value outside the range 0-65535, a compiler for a 32-bit processor could legitimately allocate a 32-bit register for it. 由于代码永远不会为
x
分配超出0-65535范围的值,因此32位处理器的编译器可以合法地为其分配32位寄存器。 Indeed, since the value of q
is never used after the first time x
is written, a compiler could use the same register to hold x
has had been used to hold q
. 实际上,由于
q
的值在第一次写入x
之后从未使用过,因此编译器可以使用相同的寄存器来保持x
已用于保持q
。 Ensuring that the function would always return a value 0-65535 would require adding some extra instructions compared with simply letting it return whatever happened to be in the register allocated to x
. 确保函数总是返回值0-65535将需要添加一些额外的指令,而不是简单地让它返回分配给
x
的寄存器中发生的任何事情。
Note that from the point of view of the Standard authors, if the Standard isn't going to require that the compiler make x
hold a value from 0-65535, it may as well not specify anything about what may happen if code tries to use x
. 请注意,从标准作者的角度来看,如果标准不要求编译器使
x
保持0-65535之间的值,那么如果代码试图使用,它也可能没有指定任何可能发生的事情。 x
。 Implementations that wish to offer any guarantees about behavior in such cases are free to do so, but the Standard imposes no requirements. 希望在这种情况下提供任何行为保证的实现可以自由地执行,但标准没有要求。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.