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结构

 位域  有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一...
  • xiven
  • xiven
  • 2009年07月13日 10:25
  • 5523

UNION和位域的使用

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

字节序 位域 联合 (bit field and union)

在c/c++语言中,如果仅仅使用状态位。可以使用位域和联合一起来使用。但是要注意字节序问题。 例如在游戏里面可以使用 一个char 8bit 来表示8种状态。比如: 地图格式属性,BUFF状...
  • sunning9001
  • sunning9001
  • 2015年05月10日 18:09
  • 363

C语言中位域(bit fields)的可移植问题

网上有文章说C语言的“位域”(bit fields)有可移植性的问题,原因是不同的编译器对位域的实现不同。   我决定用实验验证一下。   一、 实验过程:   1. 准备实验程序 ...
  • summerhust
  • summerhust
  • 2011年07月18日 22:20
  • 1203

位域,内存,大小端详解

听到好几个朋友说到去一些公司做面试,总是遇到关于大小端、位段(或者叫位域)和内存对齐的考题,然后就不知所措了。虽然我认为很多开发根本就用不到这个,但是我认为很有必要学习理解这些知识点,因为它可以让你更...
  • zrf1335348191
  • zrf1335348191
  • 2016年03月03日 11:33
  • 1322

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

转自:http://www.cnblogs.com/ToDoToTry/archive/2011/09/05/2167694.html 1:内存对齐定义:      现在使用的计算机中内存空间...
  • tht2009
  • tht2009
  • 2016年08月04日 11:58
  • 912

结构体位域在内存中的分布与平台大小端的关系

powerpc平台是大端的,x86是小端的,两者之间应用层开发有所不同,结构体位域在通讯协议打包解包中会用到很多,两种不同的平台之间通讯的时候,如何使两者匹配,这是个问题,本人深入研究了这个问题,看了...
  • qiuzhizhecsd
  • qiuzhizhecsd
  • 2017年07月15日 10:09
  • 660

C#正真实现C++中的数值型位域(非位标志)

C++中的位域成员有2种用途,一种是存放位标志的,一种是存放数值的。后一种没有搜到C#实现的例子,把实现的方式共享出来。...
  • tiger_zhao
  • tiger_zhao
  • 2015年04月16日 15:28
  • 1445

c语言之位域 -- 减少变量空间的有效利器

对c语言中位域的定义以及使用做了简单的介绍。
  • Chunfengyanyulove
  • Chunfengyanyulove
  • 2016年03月12日 17:04
  • 365

位域字节对齐

使用位域的主要目的是压缩存储,其大致规则为: 1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则 后面的字 段将紧邻前一个字段存储,直到不能容纳为止; 2) ...
  • stepsliu
  • stepsliu
  • 2014年06月05日 13:40
  • 1917
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:union及内存位域
举报原因:
原因补充:

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