简体   繁体   English

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

[英]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_MININT_MAX之间,我也知道rand()值介于0RAND_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 iINT_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_MININT_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.

相关问题 int a = ++i + ++i 是未定义的行为吗? - Is int a = ++i + ++i undefined behaviour? 为什么rand()在这个for循环中使用srand(time(null))返回相同的值? - Why does rand() return the same value using srand(time(null)) in this for loop? 为什么在使用指针时不能通过使用“ ++”来增加int变量的值? - Why can I not increment the value of an int variable by using “++” when working with pointers? 为什么我不能使用函数计算的 int 作为索引访问该数组中的值? - Why can't I access a value from this array using a functionally calculated int as an index? 为什么 rand() 一直给出相同的值? - Why rand() keep giving the same value? “(无符号)值”是否投射未定义的行为? - Is "(unsigned)value" cast undefined behaviour? 在C ++宏“ int val = rand()”中创建新值 - Create new value in C++ macro “int val = rand()” 为什么我的枚举值在用作参数时“未定义”? - Why is my enum value “undefined” when using it as a parameter? 使用 fmtlib,当值为负时,零填充数值更短,我可以调整这种行为吗? - Using fmtlib, zero padded numerical value are shorter when the value is negative, can I adapt this behaviour? int i = i ^ i的值; 它总是零或未定义的行为? - Value of int i = i ^ i ; Is it always zero or undefined behavior?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM