union及内存位域

原创 2012年03月26日 02:00:33

标准库<cstdlib>(被包含于<iostream>中)提供两个帮助生成伪随机数的函数:

函数一:int rand(void);
从srand (seed)中指定的seed开始,返回一个[seed, RAND_MAX(0x7fff))间的随机整数。

函数二:void srand(unsigned seed);
参数seed是rand()的种子,用来初始化rand()的起始值。

可以认为rand()在每次被调用的时候,它会查看:
1) 如果用户在此之前调用过srand(seed),给seed指定了一个值,那么它会自动调用
srand(seed)一次来初始化它的起始值。
2) 如果用户在此之前没有调用过srand(seed),它会自动调用srand(1)一次。

根据上面的第一点我们可以得出:
1) 如果希望rand()在每次程序运行时产生的值都不一样,必须给srand(seed)中的seed一个变值,这个变值必须在每次程序运行时都不一样(比如到目前为止流逝的时间)。
2) 否则,如果给seed指定的是一个定值,那么每次程序运行时rand()产生的值都会一样,虽然这个值会是[seed, RAND_MAX(0x7fff))之间的一个随机取得的值。
3) 如果在调用rand()之前没有调用过srand(seed),效果将和调用了srand(1)再调用rand()一样(1也是一个定值)。

举几个例子,假设我们要取得0~6之间的随机整数(不含6本身):

例一,不指定seed:
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2

例二,指定seed为定值1:
srand(1);
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
每次运行都将输出:5 5 4 4 5 4 0 0 4 2
跟例子一的结果完全一样。

例三,指定seed为定值6:
srand(6);
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
每次运行都将输出:4 1 5 1 4 3 4 4 2 2
随机值也是在[0,6)之间,随得的值跟srand(1)不同,但是每次运行的结果都相同。

例四,指定seed为当前系统流逝了的时间(单位为秒):time_t time(0):
#include <ctime>
//…
srand((unsigned)time(0));
for(int i=0;i<10;i++){ 
ran_num=rand() % 6;
cout<<ran_num<<" ";
}
第一次运行时输出:0 1 5 4 5 0 2 3 4 2
第二次:3 2 3 0 3 5 5 2 2 3
总之,每次运行结果将不一样,因为每次启动程序的时刻都不同(间隔须大于1秒?见下)。

关于time_t time(0):

time_t被定义为长整型,它返回从1970年1月1日零时零分零秒到目前为止所经过的时间,单位为秒。比如假设输出:
cout<<time(0);
值约为1169174701,约等于37(年)乘365(天)乘24(小时)乘3600(秒)(月日没算)。

另外,关于ran_num = rand() % 6,

将rand()的返回值与6求模是必须的,这样才能确保目的随机数落在[0,6)之间,否则rand()的返回值本身可能是很巨大的。
一个通用的公式是:
要取得[a,b)之间的随机整数,使用(rand() % (b-a))+ a (结果值将含a不含b)。
在a为0的情况下,简写为rand() % b。

最后,关于伪随机浮点数:

用rand() / double(RAND_MAX)可以取得0~1之间的浮点数(注意,不同于整型时候的公式,是除以,不是求模),举例:
double ran_numf=0.0;
srand((unsigned)time(0));
for(int i=0;i<10;i++){ 
ran_numf = rand() / (double)(RAND_MAX);
cout<<ran_numf<<" ";
}
运行结果为:0.716636,0.457725,…等10个0~1之间的浮点数,每次结果都不同。

如果想取更大范围的随机浮点数,比如1~10,可以将
rand() /(double)(RAND_MAX) 改为 rand() /(double)(RAND_MAX/10)
运行结果为:7.19362,6.45775,…等10个1~10之间的浮点数,每次结果都不同。
至于100,1000的情况,如此类推。

GetTickCount函数

  函数功能:GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD。

  函数原型:

  DWORD GetTickCount(void);

      随机数的产生需要有一个随机的种子,因为用计算机产生的随机数是通过递推的方法得来的,必须有一个初始值,也就是通常所说的随机种子,如果不对随机种子进行初始化,那么计算机有一个确省的随机种子,这样每次递推的结果就完全相同了,因此需要在每次程序运行时对随机种子进行初始化,在vc中的方法是调用srand(int)这个函数,其参数就是随机种子,但是如果给一个常量,则得到的随机序列就完全相同了,因此可以使用系统的时间来作为随机种子,因为系统时间可以保证它的随机性。
   调用方法是srand(GetTickCount()),但是又不能在每次调用rand()的时候都用srand(GetTickCount())来初始化,因为现在计算机运行时间比较快,当连续调用rand()时,系统的时间还没有更新,所以得到的随机种子在一段时间内是完全相同的,因此一般只在进行一次大批随机数产生之前进行一次随机种子的初始化


返回0至RAND_MAX之间的随机整数值,RAND_MAX的范围最少是在32767之间(int),即双字节(16位数)。若用unsigned int 双字节是65535,四字节是4294967295的整数范围。
0~RAND_MAX每个数字被选中的机率是相同的。

#include <stdio.h> 

void main() 
{       
union{                                                /*定义一个联合*/       
int i;       
struct{                                     /*在联合中定义一个结构*/       
char first;       
char second;       
}half;       
}number;       
number.i=0x4241; /*联合成员赋值*/       
printf("%c%c\n", number.half.first, number.half.second);       
number.half.first='a';                  /*联合中结构成员赋值*/       
number.half.second='b';       
printf("%x\n", number.i);

                         system("pause"); 


输出结果为: 
AB 
6261

分析:

union的成员是共用内存的
union{ 
int i; 
struct{ 
char first; 
char second;
}half;
}number; 
number.i=0x4241;

在这里i 和 half结构是共用内存

number.i=0x4241给i赋值后,内存中以二进制存储0100 0010 0100 0001
按顺序对应到结构中
halt.first=01000010   转换成10进制就是66(字母A的asc码)
halt.second=01000001 转换成10进制是65   (字母B的asc码)
所以输出后就是 AB



http://hi.baidu.com/hankcs/blog/item/f57d9f2834723ef499250a91.html

http://zhidao.baidu.com/question/115416879.html

http://blog.csdn.net/yanyiyyy/article/details/6590092

相关文章推荐

UNION和位域的使用

以下讲解都是在VS2012中进行试验的: 联合体和位域的使用都是以节省空间为目的。 联合体同stuct一样,联合默认方位权限也是共有的,并且,也具有成员函数。 共用体和结构体有以下区别: 1.共用体内...

struct位域,对齐以及union作为class需要注意的地方

一. struct对齐在c/c++中,struct结构体的大小不是简单的成员变量所占空间大小的累加,这里面涉及到变量对齐(alignment)的概念,由于计算机中内存的结构,使得cpu从某个特定边界的...
  • orzlzro
  • orzlzro
  • 2011年05月07日 00:04
  • 2198

sizeof详解、类的大小、内存对齐、位域

概述sizeof这个知识点几乎是程序员找工作笔试必考的题目。已经遇到过几次,深受其害,有必要总结一下了。 sizeof是C/C++中的关键字,它是一个运算符,其作用是取得一个对象(数据类型或者数据对...

c语言中内存对齐与位域对齐

一。内存对齐 许多计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数k(通常它为4或8)的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(a...

内存分配对齐策略(含位域模式)

内存对齐定义: ----------- 现在使用的计算机中内存空间都是按照字节划分的,从理论上讲似乎对任何类型的变量的访问可 以从任何地址开始,但是实际上计算机系统对于基本数据类型在内存...

LinuxC简谈之结构体的内存对齐和位域的存储

结构体的成员可以是很多的类型,结构体类型可以定义结构体类型的变量,这样就有各种类型的成员变量。那么,在内存中这些成员变量是如何存储的呢?今天我把我对此的一些理解分享一下。首先是结构体的内存对齐。接下来...

结构体,指针嵌套内存对其位域条件编译

结构体,指针嵌套内存对其位域条件编译,枚举,判断大小端,typedef各种使用方法...

内存对齐与位域

内存对齐:在讨论之前我们先看一个栗子:#includeusing namespae std;int main() { struct A { int a; cha...

C语言结构体的大小——内存对齐和位域的使用

C语言结构体对齐 C语言结构体对齐也是老生常谈的话题了。基本上是面试题的必考题。内容虽然很基础,但一不小心就会弄错。写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结...

C++随记总结(1)----关于C++中的大小端、位段(惑位域)和内存对齐

听到好几个朋友说到去一些公司做面试,总是遇到关于大小端、位段(或者叫位域)和内存对齐的考题,然后就不知所措了。虽然我认为很多开发根本就用不到这个,但是我认为很有必要学习理解这些知识点,因为它可以让你更...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:union及内存位域
举报原因:
原因补充:

(最多只允许输入30个字)