数据类型分为:
char //字符型数据类型
int //整形
short //短整型
long //长整形
long long //更长的整形
float //单精度浮点型
double //双精度浮点型
char
unsigned char 无符号的字符类型
signed char 有符号的字符类型等同于 char
int
unsigned int
signed
short
unsigned short [int]
signed short [int]
long
unsigned long [int]
signed long [int]
double
float
数组类型
结构体类型 strcut
枚举类型 enum
联合体类型 union
int *p1
char *p2
double *p3
float *p4
void * p5
void 表示为空类型
通常用于函数的返回值类型,函数的参数,指针类型
在计算机中数据是以二进制的形式进行存储的
有符号的数有三种表示形式:原码,反码,补码。
补码=反码+1
对于正整数:原码,反码,补码,相同
对于整型:在内存中存储的是补码
我们先用补码看一看,他是多少?
6的原码,反码,补码相同都为
0000 0000 0000 0000 0000 0000 0000 0110
在内存存储是以十六进制进行存储的
00 00 00 06
-2的原码
1000 0000 0000 0000 0000 0000 0000 0010
反码
1111 1111 1111 1111 1111 1111 1111 1101
补码
1111 1111 1111 1111 1111 1111 1111 1110
以十六进制表示
FF FF FF Fe
为什么它是倒着存放的呢? 在这里我们就要讨论大小端问题啦
大端存储模式:是指数据的低位保存在内存中的高地址中,而数据的高地址保存在内存的低地址中
小端存储模式:是指数据的高位保存在内存中的高地址中,而数据的低地址保存在内存的低地址中
用图来分析更为直观
2015年百度面试题
请简述大端字节序和小端字节序的概念,设计一个小程序,判断你当前机器上的字节序
#include
int Judge(int n)
{
char *m = (char*)n;
if (*m == 1)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
int n = 1;
//00000000000000000000000000000001
//char 截取 一个字节8个bit位 00000001
//小端为 10 00 00 00
//大端为 00 00 00 01
int ret = Judge(n);
if (ret == 1)
{
printf("小端字节序\n");
}
else
{
printf("大端字节序\n");
}
return 0;
}
引例:
#include
int main()
{
int n = 9;
float *pFloat = (float *)&n;
printf("n的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
*pFloat = 9.0;
printf("num的值为:%d\n",n);
printf("*pFloat的值为:%f\n",*pFloat);
return 0;
}
在我们没有学习,浮点型数据在内存中的存储式,我妄自揣测一下大家应该是这样想的把
int n 的地址被强制类型转化成 float
第一个输出为 9
第二个输出为 9.000000
第三个输出为 9
第四个输出为 9.000000
但是输出却不是这样,这是为什么呢?
那就进入正题喽
浮点型在内存中的存储 和 整形存储有这不一样的地方
在这里
根据国际标准IEEE(电气和电子工程协会) 754,任意一个二进制浮点数V可以表示成下面的形式:
(-1)^S * M * 2^E
(-1)^s表示符号位,当s=0,V为正数;当s=1,V为负数。
M表示有效数字,大于等于1,小于2。
2^E表示指数位
举例来说:
十进制的5.0,写成二进制是 101.0 ,相当于 1.01×2^2 。 那么,按照上面V的格式,可以得出s=0,
M=1.01,E=2。
十进制的-5.0,写成二进制是 -101.0 ,相当于 -1.01×2^2 。那么,s=1,M=1.01,E=2
IEEE 754对有效数字M和指数E,还有一些特别规定。 前面说过, 1≤M<2 ,也就是说,M可以写成 1.xxxxxx 的形
式,其中xxxxxx表示小数部分。为了能够存储更多的位数,略去1
至于指数E,情况就比较复杂。 首先,E为一个无符号整数(unsigned int)这意味着,如果E为8位,它的取值范围为0~255;如果E为11位,它的 取值范围为0~2047。但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8位的E,这个中间数是127;对于11位的E,这个中间数是1023。比如,2^10的E
是10,所以保存成32位浮点数时,必须保存成10+127=137,即10001001例
5.0的存储
101.0
1.01x2^2
M=1.01
E=2
S=2
0 00000010 01000000000000000000000
然后,指数E从内存中取出还可以再分成三种情况:
1.E不全为0或不全为1
这时,浮点数就采用下面的规则表示,即指数E的计算值减去127(或1023),得到真实值,再将有效数字M前加上第一位的1。
在这里计算 0.5
0.5 转化成为二进制形式 为 0.1,因为M部分必须为1.……,所以讲M向前移意为变成(1.0)*2^(-1)
所以E = -1+127=126
M=23个0
S = 0
所以二进制形式为 0 01111110 00000000000000000000000
2.E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值, 有效数字M不再加上第一位的1,而是还原为
0.xxxxxx的小数。这样做是为了表示±0,以及接近于0的很小的数字。
3.E全为1
这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位s);
计算输出的结果是什么
1.
#include
int main()
{
char a = -1;
//sign char 和 char 都是一个意思
signed char b = -1;
unsigned char c = -1;
//10000001
//11111110
//11111111 无符号数
//%d 输出 整型提升 无符号的整形提升,各位补零
//00000000 00000000 00000000 11111111 原,反,补,相同
printf("a=%d,b=%d,c=%d", a, b, c);
return 0;
}
#include
int main()
{
char a = -128;
//char 的范围是-128 到 127
//要打印一个无符号数
//原码 10000000 00000000 00000000 10000000
//反码 11111111 11111111 11111111 01111111
//补码 11111111 11111111 11111111 10000000
//char 类型 截取 10000000
//整形提升 最高位为1,认为符号位
// 11111111 11111111 11111111 10000000
// 此处打印为,无符号整数 打印 所以认为 11111111 11111111 11111111 10000000全部为有效位
// 4294967168
printf("%u\n", a);
return 0;
}
#include
int main()
{
char a = 128;
//00000000 00000000 00000000 10000000 原,反,补,相同
//char 类型 1 0000000 1为符号位
//整形提升 11111111 11111111 11111111 10000000
// 4294967168
printf("%u\n", a);
return 0;
}
#include
int main()
{
int i = -20;
unsigned int j = 10;
// -20
//10000000 00000000 00000000 00010100 原码
//11111111 11111111 11111111 11101011 反码
//11111111 11111111 11111111 11101100 补码
//10
//00000000 00000000 00000000 00001010 原码 原 ,反,补 相同
// -20+10
//11111111 11111111 11111111 11110110 补码
//11111111 11111111 11111111 11110101 反码
//10000000 00000000 00000000 00001010 原码
//-10
printf("%d\n", i + j);
return 0;
}
#include
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)
{
printf("%u\n", i);
}
//因为i是无符号数,所以他被无论怎么减,都会大于0
//所以死循环
return 0;
}
在打印中也可以看到,unsigned int 的值的范围:0到429467295
6 .
#include
int main()
{
char a[1000];
int i;
for (i = 0; i < 1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));
return 0;
}
#include
unsigned char i = 0;
int main()
{
for (i = 0; i <= 255; i++)
{
printf("hello world\n");
}
//死循环打印hello world
//因为unsigned char 的范围 为0~255,所以无论如何,都在0~255 255+1就进入下一个循环,从0开始
return 0;
}