数据类型的介绍
我们知道一些基本数据数据类型的使用,例如
类型的意义:
- 使用这个类型开辟内存空间的大小(大小决定了使用范围)。
- 如何看待内存空间的视角
类型的基本归类:
整形:
浮点型:
还有一些构造类型、指针类型、空类型等。
整形在内存中的存储
我们知道过一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同的类型而决定的。
那接下来我们谈谈数据在所开辟内存中到底是如何存储的`
int a=20; int b=-10;
可以知道a和b都是整形分配了4个字节,那么他们是如何存储的呢?
原码、反码、补码
在此之前我们需要了解一下计算机中整数的三种二进制的表示方法。相信大家一定有所了解,在这里给大家简单介绍一下。
三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位
正数的原、反、补码都相同。
负整数的三种表示方法各不相同。
所以我们在此只说一下负数的情况
对于原码来说,正负数都是直接转化为二进制数即可得到该数的原码。
对于反码来说,原码的符号位不变,其他位取反即可得到。
对于补码来说,给反码+1即可得到补码。
对于整形来说:数据存放内存中其实存放的是补码。
为什么呢?
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统
一处理;
同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程
是相同的,不需要额外的硬件电路。
那么我们了解了之后看一下在内存中a和b的存储情况
int a=20; //正数的原码补码相同 //00000000000000000000000000010100 在内存中存储是16进制我们将其转化为16进制 //0000 0000 0000 0000 0000 0000 0001 0100 //00 00 00 14 (16)
再看一下b的情况
int b=-10; //原码 10000000000000000000000000001010 //反码 11111111111111111111111111110101 //补码 1111 1111 1111 1111 1111 1111 1111 0110 //十六进制ff ff ff f6
但这种情况似乎和存储的情况不太一样。
大小端介绍
什么大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址 中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地 址中。
为什么有大端和小端:
为什么会有大小端模式之分呢?这是因为在计算机系统中,我们是以字节为单位的,每个地址单元
都对应着一个字节,一个字节为8 bit。但是在C语言中除了8 bit的char之外,还有16 bit的short
型,32 bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32
位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。因
此就导致了大端存储模式和小端存储模式。
例如:一个 16bit 的 short 型 x ,在内存中的地址为 0x0010 , x 的值为 0x1122 ,那么 0x11 为
高字节, 0x22 为低字节。对于大端模式,就将 0x11 放在低地址中,即 0x0010 中, 0x22 放在高
地址中,即 0x0011 中。小端模式,刚好相反。我们常用的 X86 结构是小端模式,而 KEIL C51 则
为大端模式。很多的ARM,DSP都为小端模式。有些ARM处理器还可以由硬件来选择是大端模式
还是小端模式。
我常用的编译器是vs,那么我们来验证一下,使用vs验是大端存储还是小端存储
#include<stdio.h> int check_sys() { int i = 1;//定义一个变量i=1 return (*(char*)&i);//取出变量i的地址强制转化为(char*)类型 返回首字节的值 } int main() { //1的16进制为00 00 00 01 //若小端存储则首字节为01即为1 int ret = check_sys(); if (ret == 1) { printf("小端存储"); } else { printf("大端存储"); } return 0; }
练习
#include <stdio.h> int main() { char a= -1; signed char b=-1; unsigned char c=-1; printf("a=%d,b=%d,c=%d",a,b,c); return 0; }
我们刚刚已经了解了整形的存储方式那么不妨来试一下这样一道题。
运行结果是 -1 -1 255
相信大家能知道为什么a和b是-1,那么接下来来分析一下为什么是255
unsigned char c=-1; //原码 10000000000000000000000000000001 //反码 11111111111111111111111111111110 //补码 11111111111111111111111111111111 //因为unsigned char 仅一个字节所以截取8个bit位即为 // 11111111 //对于unsigned来说没有符号位则将111111111转化为10进制即为255
那么我们再来看另一道题
#include <stdio.h> int main() { char a = -128; printf("%u\n",a); return 0; }
我们来逐步分析一下
char a=-128; //原码 10000000000000000000000010000000 //对于char型只能取一个字节也就是10000000 //打印为整形对其作整形提升也就是 // 11111111111111111111111110000000 //%u 打印无符号的整数,也就是将补码11111111111111111111111110000000 //转化为10进制
结果是一样的,说明确实是这样进行存储的,如果大家不懂如何整型提升的话,向大家推荐一篇文章给大家详细了解整型提升:
http://t.csdn.cn/RfDIU 原作者:@bit_Sakura
那么我们来分析一下char——假设 是有符号的char
所以signed char的范围是-128~127
如果是无符号的unsigned char
所以unsigned char的范围是0·255