我一直在努力创建没有rand()的随机数字(只是因为我喜欢尝试的东西)。使用在线编译器,这非常有用:
#include <iostream>
int randNum()
{
unsigned int x;
size_t y = reinterpret_cast<size_t>(&x);
return ((y >> 16) & 0x0000FFFF);
}
int main()
{
unsigned int x = randNum();
std::cout << x;
return 0;
}
在我的计算机上本地编译,但不是那么多。每次编译并运行它时,它都会将x分配给相同的内存地址。
我能理解为什么在线编译器每次都会给我一个新的内存地址,但为什么不在我的本地机器上呢?
答案 0 :(得分:4)
我能理解为什么在线编译器每次都会给我一个新的内存地址,但为什么不在我的本地机器上呢?
简短回答:因为标准中没有任何内容可以保证内存地址每次都相同或不同。这取决于您运行程序的位置(平台,操作系统),编译方式以及其他一千多个因素。
在您的代码中不依赖于此类内容。最重要的是,如果您需要为实际项目生成随机数,请使用<random>
或PCG。
答案 1 :(得分:0)
首先你需要一点背景知识。每个程序都从操作系统中获取虚假的RAM地址。它被称为虚拟地址空间,它允许进程表现得像拥有整个内存一样。该过程不必担心与其他正在运行的进程冲突。当它尝试访问内存位置时,操作系统会将虚拟地址转换为真实的“物理”地址。如果你对此感兴趣,你应该查看页表。
进程有3个主要内存区域。堆栈,堆和文本。堆栈保留了函数堆栈以及这些函数中定义的局部变量,例如unsigned int x。
你的randNum只是返回堆栈底部的当前位置。 (顺便说一句,这是一种安全风险)。通过简单的测试,randNum将始终返回相同的结果,因为x的地址基于堆栈。
好的,你可能想知道为什么堆栈基地总是在同一个地方开始。尽管它有一点摆动空间,但堆栈始终位于地址空间的顶部(高数字)端,例如0xBFFF0000,并且它向下“增长”,朝向低数字。当您进行右移(y>&gt; 16)时,您实际上正在查看地址中变化最小的部分,这恰好是页面索引,可以由数百个生活变量共享的部分在同一页上。
可能影响堆栈基础位置的事情:
我敢打赌,在线编译器发生的事情是每次在不同的机器上进行编译时。每次运行时,它都在不同的机器上运行。很多人同时访问服务器,也许它对环境变量有影响?而当你在本地机器上运行时,事情相对安静。
所以我想说这是一个好主意,虽然它不起作用,但我希望你能学到一些有趣的东西。