跟我学“数据结构”系列: (1) 用程序探索数据

 

跟我学“数据结构”系列:用程序探索数据
摘要:
关键字
引言
在开始数据结构之前,我们先来一节基础课:“数据”
最近数十年来,计算机领域高速发展,计算机已深入到各行各业,已能处理像如文字、图形、图像、声音等代表不同属性的信息。本文从程序员观点,利用 c++ 程序来探索计算机是如何表示和处理数据的。
适用的读者 :
初级
相关性:
    本文是学习后续“数据结构”课程的基础。
二进制
电脑内部为什么要用二进制呢?这是因为二进制中只有两个数,即 0 1 。二进制数在电气元件中容易实现、容易运算,在电子学中具有两种稳定状态以代表 0 1 。而需要由 0 1 来代表的量很多。如:电压的高和低,电灯的亮和灭,电容的充电和放电,脉冲的有和无,晶体管的导通和截止等。总之,电脑内部使用二进制,主要是为了设计和制造电脑方便。
先假定普通灯泡只有亮、灭两种状态。以灯泡为工具,我们来探析计算机中数据是如何表示的:  我们把一个灯泡称为一“位”,当有一“位”灯泡(用格子表示)的时候,能表示两个数,这两个数 0 1
 [p1.jpg]
 
由上图可见,一位可表示 2 个数;二位可以表示 4 个数,三位可以表示 8 个数,即 2 3 次方, 4 位可以表示 2 4 次方个数, 16 位可以表示 2 16 次方个数, 32 位表示能表示 2 32 次方个数( 0 4294967295 )。
我们常说的 8 位机(如任天堂游戏机), 16 位机(如早期的 286 ),以及 32 位机(最近几年的主流 PC 机),现在有些服务器是 64 位机,我们的桌面电脑也即将过渡至 64 位。 这里说的“位数”就指在计算机系统中,一个寄存器有多少个可以表示01的小格子的个数 。这也指整型数据类型或指针类型的位数。
表示信息的单位
位和字节: 是计算机中信息的最小的元素。但这个单位实在太小了,制造计算机的时候,一般会把 8 个“位”合在一起,称为一个字节。字节是计算机处理信息的最小单位。
 
信息表示形式
日常人们通常用十进制来表示一个数。如 100 分。由于计算机更容易处理二进制,用二进制表示 100 ,二进制表示为 1100100 ,用 16 表示为 0x64 ,图解如下:
C++程序来探索计算机数据的表示方式
代码 1:
使用 C++ iostream 显示数据。
Code:
  1. //file:1esson.cpp   
  2. //   
  3.   
  4. #include<iostream>   
  5. #include<iomanip>   
  6. #include<string>   
  7. using namespace std;   
  8.   
  9.      
  10. void showBytes(unsigned char* p, size_t length);   
  11. void showUINT(unsigned  int x);   
  12.   
  13. template <typename T> void showType( T x);   
  14. template <typename T> void showTypeWithName( T x,string typeName);   
  15.   
  16. void swapUINT32(unsigned int * ptr);   
  17. void swapUINT16(unsigned short int* ptr);   
  18.   
  19. int main(int argc, char* argv[])   
  20. {   
  21.     cout << argv[0] << "start here." << endl;   
  22.     cout << "this program illustrates how to use iostream." << endl;   
  23.     
  24.     unsigned int x = 100;   
  25.     cout << "decimal format:" << dec << x << endl;   
  26.     cout << "octal  format:" << oct << x << endl;   
  27.     cout << "hexadecimal format:" << hex << x << endl;   
  28.     cout << "address is :" << &x << endl;   
  29.     cout << "sizeof (unsigned int) in my computer is :" << sizeof (unsigned int) << endl;   
  30.     cout << "sizeof (signed int ) in my computer is :" << sizeof (signed int) << endl;   
  31.     cout << "sizeof (char ) in my computer is :" << sizeof (char) << endl;   
  32.     cout << "sizeof (unsigned char ) in my computer is :" << sizeof (unsigned char) << endl;   
  33.     cout << "sizeof (short ) in my computer is :" << sizeof (short) << endl;   
  34.     cout << "sizeof (long ) in my computer is :" << sizeof (long) << endl;   
  35.     cout << "sizeof (double ) in my computer is :" << sizeof (double) << endl;   
  36.     cout << "sizeof (float ) in my computer is :" << sizeof (float) << endl;   
  37.        
  38.     cout << "we are explore the unsigned int " << x << " in my compute. "<< endl;   
  39.     showUINT(x);   
  40.   
  41.     cout << "we are explore more ..."  << endl;   
  42.     unsigned int a = 1u;   
  43.     unsigned int b = 8u;   
  44.     unsigned int c = 65535u;   
  45.     unsigned int d = 10000u;   
  46.     unsigned int e = 4294967294u;   
  47.     showUINT(a);   
  48.     showUINT(b);   
  49.     showUINT(c);   
  50.     showUINT(d);   
  51.     showUINT(e);   
  52.   
  53.        
  54.     showType<unsigned int> (x);   
  55.   
  56.     float f = 3.14f;   
  57.     showType<float> (f);   
  58.   
  59.     showTypeWithName<float> (f,"float");   
  60.     showTypeWithName<double> (3.14,"double");   
  61.   
  62. /*  
  63.     for(unsigned int i = 0; i < e; i++)  
  64.     {  
  65.         showUINT(i);  
  66.     }  
  67. */     
  68.     cout << "/nwe are explore byte endian"  << endl;   
  69.     cout<< "before swapping byte  : " ;   
  70.     x = 0x12345678; //   
  71.     cout << " x = " << hex << "0x" << x << "   dec:" << dec << x<<  endl;   
  72.   
  73.     showUINT(x);   
  74.     swapUINT32(&x);   
  75.     cout<< "before swapping byte  : " ;   
  76.     showUINT(x);   
  77.   
  78.     x = 0x12345677;   
  79.     cout << " x = " << hex << "0x" << x << "   dec:" << dec << x<<  endl;   
  80.     cout<< "before swapping byte  : " ;   
  81.     showUINT(x);   
  82.     swapUINT32(&x);   
  83.     cout<< "before swapping byte  : " ;   
  84.     showUINT(x);   
  85.   
  86.   
  87.     x = 0x12345679;   
  88.     cout << " x = " << hex << "0x" << x << "   dec:" << dec << x<<  endl;   
  89.     cout<< "before swapping byte  : " ;   
  90.     showUINT(x);   
  91.     swapUINT32(&x);   
  92.     cout<< "after swapping byte  : " ;    // thanks 岑梓源
  93.     showUINT(x);   
  94.   
  95.   
  96.   
  97.   
  98.   
  99.     return 0;   
  100. }   
  101.   
  102.   
  103. void showBytes(unsigned char* p, size_t length)   
  104. {   
  105.     unsigned int i = 0;   
  106.     for(i = 0; i < length ; i++)   
  107.     {   
  108.         //printf(" %.2x",p[i]);   
  109.         cout<<hex<<setw(2)<<right<<setfill('0')<<(int)p[i] << " ";   
  110.     }   
  111.     cout << endl;   
  112. }   
  113.   
  114.   
  115.   
  116. void showUINT(unsigned int x)   
  117. {   
  118.   
  119.     showBytes((unsigned char*)&x, sizeof (unsigned int));   
  120. }   
  121.   
  122. template < typename T > void showType(T x)   
  123. {   
  124.     cout << "Type size is: " << sizeof (T) << "   ";   
  125.     showBytes((unsigned char* )&x, sizeof (T));   
  126.   
  127. }   
  128.   
  129. template < typename T > void showTypeWithName(T x,string typeName)   
  130. {   
  131.     cout << typeName << " size is: " << sizeof (T) << "   ";   
  132.     showBytes((unsigned char* )&x, sizeof (T));   
  133.        
  134. }   
  135.   
  136. void swapUINT32(unsigned int* ptr)   
  137. {   
  138.     unsigned char*  p = (unsigned char*) ptr;   
  139.     unsigned char t = p[0];   
  140.     p[0] = p[3];   
  141.     p[3] = t;   
  142.     t = p[2];   
  143.     p[2] = p[1];   
  144.     p[1] = t;   
  145. }   
  146.   
  147. void swapUINT16(unsigned short int* ptr)   
  148. {   
  149.   
  150.     unsigned char*  p = (unsigned char*) ptr;   
  151.     unsigned char t = p[0];   
  152.     p[0] = p[1];   
  153.     p[1] = t;   
  154. }   
  155.   
  运行结果示意图:
 
字节序(endian
人们在写的时候,一般是高位在前,低位在后。比如数 305,419,896 (0x12345678) ,它的高位是 3 表示 3 亿,是高位, 6 表示 6 个,是最低位。 8 表示 8 百,它的高位在左边,低位在右面。但从我们的输出上看,计算机存储这个数的时候,高低在右边,低位在左边。如下图:
值得注意的是,并不是所有的计算机都是低位节在前,高位字节在后。
高位在前的表示方法俗称“大端”法,反之叫“小端”,字节序这个名称有一个有趣的来源。
“endian” 这个词出自《格列佛游记》。小人国的内战就源于吃鸡蛋时是究竟从大头 (Big-Endian) 敲开还是从小头 (Little-Endian) 敲开,由此曾发生过六次叛乱,其中一个皇帝送了命,另一个丢了王位。
 
结束语

本节课通过代码,揭示了数据在计算机内部的表示方法,更多内容与计算机原理中会有详细描述。计算机原理也是一门很有趣的课程。本节课中的代码还用到C++函数,模板函数,数组,这些内容我们在后续的课程中还会进一步的讲解。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 36
    评论
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值