MyException - 我的异常网
当前位置:我的异常网» C语言 » 深入了解C语言-02-数据编码

深入了解C语言-02-数据编码

www.MyException.Cn  网友分享于:2014-03-08  浏览:0次
深入理解C语言-02-数据编码

信息系统建模中,第一步是信息的编码,也就是说,信息如何在计算机中存储。

为了硬件设计的简单,通常使用芯片均采用二进制。并且,由于科技的局限性,数据的长度也是有限的。

比如,现在大多数电脑的数据总线是32位/或者64位。以32位系统为例,能编码的集合大小为 2的32次方,也就是4294967296。


显然这是一个有限集合。而现实中的模拟信息通常是无限集合。

这就涉及到信息的编码,即建立一个映射函数: f(信息)=计算机中的信息编码。


信息的编码设计涉及到数据的大小选择,实际项目中一般是考虑当前需求和后期的扩展选择一个折中值。


对于C语言来说,主要考虑以下3个方面:

数据类型的大小

数据的字节序

数据的对齐


数据类型大小的差异是C语言可移植性方面的大问题。


为此,在新系统使用前,需要参考芯片手册(DataSheet)或写如下代码进行测试。

printf("char[%d] short[%d] int[%d] long[%d] long long[%d] float[%d] double[%d] \n",
sizeof(char), sizeof(short), sizeof(int), sizeof(long), sizeof(long long), 
sizeof(float), sizeof(double));


在32位系统,一般返回以下结果:

char[1] short[2] int[4] long[4] long long[8] float[4] double[8]


数据的字节序

通常,x86架构采用的是小端表示(Little-Endian), MIPS架构采用的是大端表示(BigEndian)。

比如0x12345678 在x86中是 按照 0x78 0x56 0x34 0x12 的顺序依次存储,

而在MIPS架构中则通常是按照 0x12 0x34 0x56 0x78   的顺序依次存储。

可以写以下代码来测试大小端:

int checkEndian()
{
int x = 0x12345678;
if (*(char*)(&x) == 0x78) {
printf("Little Endian\n");
return 0;
} else {
printf("Big-Endian");
return 1;
}
}


数据的对齐:

为什么要考虑对齐? 一方面是为了性能考虑,另一方面则是芯片设计上的限制。

比如公司使用的MIPS芯片要求数据地址必须4字节对齐,否则就会总线错误(Bus Error)


当然,按照时间空间的矛盾性,对齐必然会导致内存的浪费。这样在E2ROM使用上来说,也就意味着硬件成本的上升。


如何节约? 一种办法是牺牲时间,进行数据压缩。还有一种更方便的办法就是自己控制对齐。

当然,最好的设计就是从整体上考虑对齐,合理安排数据的位置。


控制对齐的方式与编译器有关系,通常:

gcc采用

__attribute__ ((aligned (n))

vc采用:

#pragma pack(n)


可以写如下代码进行测试:

VC:

typedef struct  stTest1 
{
char ch;
int x;
short y;
} Test1;


#pragma pack(1)
typedef struct  stTest2
{
char ch;
int x;
short y;
} Test2;
#pragma pack(4)


gcc:

typedef struct  stTest1 
{
char ch;
int x;
short y;
} Test1;


typedef struct  stTest2
{
char ch;
int x;
short y;
} Test2 __attribute__ ((aligned (1));


Log代码:

printf("sizeof(Test1)= %d, sizeof(Test2) = %d \n", sizeof(Test1), sizeof(Test2));
printf("__alignof(Test1)= %d, __alignof(Test2) = %d \n", __alignof(Test1), __alignof(Test2));


输出:

sizeof(Test1)= 12, sizeof(Test2) = 7
alignof(Test1)= 4, __alignof(Test2) = 1


接下来就是数据的表示。

通常我们有以下方式:

1> 利用bit位,设计每一个数据的存储位置与大小。

比如一副扑克牌,有4种花色,每一种花色有13种取值,这样我们便可以按如下方式编码:

1个字节有8个Bit位, 0-3 4个Bit 表示A-K, 4-5 2个Bit表示花色,大小王特殊编码。

8个Bit    7    6     5       4       3      2      1  0

                                                |                    |

                                                —— ————     ->  0001 -> A,  0001-> 2, ..., 1101 -> K 

                             |         |

                             ——     ->  00 -> 红桃 01-> 黑桃  02-> 黑梅 03 -> 红方

大王:       000000

小王:       111111


2> 利用C语言提供的基本数据类型(char, short, int, unsign int, float, double),并配合数组与结构体来构建复杂数据结构。

    对于,非线性结构,还需要指针来配合。

在使用基本类型前,按照C语言的设计哲学(谁使用谁负责理念),必须搞懂以下几点:

1> 各种格式的表示范围

2> 数据的二进制值是什么

3> 是否有精度丢失或数据溢出?如何判断?


2.1 表示范围

以无符号整数为例,在32位系统下:

unsigned char     8位    表示范围   0~255  

unsigned short    16位    表示范围   0~65535

unsigned long   32位    表示范围   0~4294967295

unsigned long long   64位    表示范围   0~18446744073709551615

 

这些值并不需要记忆精确值,只需要大致了解级数就可以了。

具体值我们可以通过下面代码来了解:

#include<limits.h>

int testLimit()
{
printf("min of char: %d \n", SCHAR_MIN);
printf("max of char: %d \n", SCHAR_MAX);
printf("min of short: %d \n", SHRT_MIN);
printf("max of short: %d \n", SHRT_MAX);
printf("min of int: %d \n", INT_MIN);
printf("max of int: %d \n", INT_MAX);
printf("min of long: %d \n", LONG_MIN);
printf("max of long: %d \n", LONG_MAX);
printf("min of long long: %llu \n", LLONG_MIN);
printf("max of long  long: %llu \n", LLONG_MAX);


printf("max of unsigned char: %d \n", UCHAR_MAX);
printf("max of unsigned short: %d \n", USHRT_MAX);
printf("max of unsigned int: %u \n", UINT_MAX);
printf("max of unsigned long: %u \n", ULONG_MAX);
printf("max of unsigned long long: %llu \n", ULLONG_MAX);
return 0;
}

在32位系统上输出:

min of char: -128
max of char: 127
min of short: -32768
max of short: 32767
min of int: -2147483648
max of int: 2147483647
min of long: -2147483648
max of long: 2147483647
min of long long: 9223372036854775808
max of long long: 9223372036854775807
max of unsigned char: 255
max of unsigned short: 65535
max of unsigned int: 4294967295
max of unsigned long: 4294967295
max of unsigned long long: 18446744073709551615

关于浮点数请参考float.h头文件。以下翻译来自百度文库:

double:


 DBL_DIG double小数点后面精确的位数 
 DBL_EPSILON  最小的尾数 (1.0+DBL_EPSILON != 1.0)

 DBL_MANT_DIG 尾数中的位数 
 DBL_MAX 最大值  

 DBL_MAX_10_EXP 最大10进制指数 
 DBL_MAX_EXP 最大2进制指数 

 DBL_MIN 最小值  

 DBL_MIN_10_EXP 最小10进制指数
 DBL_MIN_EXP 最小2进制指数 


float :

  FLT_DIG float小数点后面精确的位数
  FLT_EPSILON 最小的尾数 (1.0+FLT_EPSILON != 1.0)

  FLT_MANT_DLG 尾数中的位数 
  FLT_MAX 最大值  

  FLT_MAX_10_EXP 最大10进制指数 

FLT_MAX_EXP 最大2进制指数 
FLT_MIN 最小值  

FLT_MIN_10_EXP 最小10进制指数 
FLT_MIN_EXP 最小2进制指数
 
FLT_RADIX 进制基数 FLT_ROUNDS 加法舍入 

long double:

  LDBL_DIG long double小数点后面精确的位数 
  LDBL_EPSILON 最小的尾数 (1.0+LDBL_EPSILON != 1.0)
  LDBL_MANT_DLG 尾数中的位数 

 LDBL_MAX 最大值 
 LDBL_MAX_10_EXP 最大10进制指数 

 LDBL_MAX_EXP 最大2进制指数 

 LDBL_MIN 最小值  

 LDBL_MIN_10_EXP 最小10进制指数 

 LDBL_MIN_EXP 最小2进制指数  

文章评论

初级 vs 高级开发者 哪个性价比更高?
初级 vs 高级开发者 哪个性价比更高?
我是如何打败拖延症的
我是如何打败拖延症的
程序员的鄙视链
程序员的鄙视链
10个调试和排错的小建议
10个调试和排错的小建议
老美怎么看待阿里赴美上市
老美怎么看待阿里赴美上市
“懒”出效率是程序员的美德
“懒”出效率是程序员的美德
程序员应该关注的一些事儿
程序员应该关注的一些事儿
十大编程算法助程序员走上高手之路
十大编程算法助程序员走上高手之路
程序员都该阅读的书
程序员都该阅读的书
“肮脏的”IT工作排行榜
“肮脏的”IT工作排行榜
代码女神横空出世
代码女神横空出世
老程序员的下场
老程序员的下场
Java程序员必看电影
Java程序员必看电影
看13位CEO、创始人和高管如何提高工作效率
看13位CEO、创始人和高管如何提高工作效率
编程语言是女人
编程语言是女人
为啥Android手机总会越用越慢?
为啥Android手机总会越用越慢?
做程序猿的老婆应该注意的一些事情
做程序猿的老婆应该注意的一些事情
为什么程序员都是夜猫子
为什么程序员都是夜猫子
如何成为一名黑客
如何成为一名黑客
Web开发者需具备的8个好习惯
Web开发者需具备的8个好习惯
10个帮程序员减压放松的网站
10个帮程序员减压放松的网站
程序员周末都喜欢做什么?
程序员周末都喜欢做什么?
团队中“技术大拿”并非越多越好
团队中“技术大拿”并非越多越好
60个开发者不容错过的免费资源库
60个开发者不容错过的免费资源库
那些争议最大的编程观点
那些争议最大的编程观点
程序员最害怕的5件事 你中招了吗?
程序员最害怕的5件事 你中招了吗?
程序猿的崛起——Growth Hacker
程序猿的崛起——Growth Hacker
如何区分一个程序员是“老手“还是“新手“?
如何区分一个程序员是“老手“还是“新手“?
程序员必看的十大电影
程序员必看的十大电影
漫画:程序员的工作
漫画:程序员的工作
总结2014中国互联网十大段子
总结2014中国互联网十大段子
一个程序员的时间管理
一个程序员的时间管理
亲爱的项目经理,我恨你
亲爱的项目经理,我恨你
每天工作4小时的程序员
每天工作4小时的程序员
不懂技术不要对懂技术的人说这很容易实现
不懂技术不要对懂技术的人说这很容易实现
5款最佳正则表达式编辑调试器
5款最佳正则表达式编辑调试器
程序员眼里IE浏览器是什么样的
程序员眼里IE浏览器是什么样的
什么才是优秀的用户界面设计
什么才是优秀的用户界面设计
当下全球最炙手可热的八位少年创业者
当下全球最炙手可热的八位少年创业者
科技史上最臭名昭著的13大罪犯
科技史上最臭名昭著的13大罪犯
我的丈夫是个程序员
我的丈夫是个程序员
鲜为人知的编程真相
鲜为人知的编程真相
聊聊HTTPS和SSL/TLS协议
聊聊HTTPS和SSL/TLS协议
Web开发人员为什么越来越懒了?
Web开发人员为什么越来越懒了?
程序员的一天:一寸光阴一寸金
程序员的一天:一寸光阴一寸金
软件开发程序错误异常ExceptionCopyright © 2009-2015 MyException 版权所有