1. 基本数据类型
C语言基本数据类型包括:
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度
1.1 类型的意义
1.决定了使用这个类型开辟内存空间的大小(使用范围)
2.如何看待内存空间的视角
1.2 类型的基本归类
1.2.1 整形家族:
char
unsigned char
signed char
short
unsigned short [ int ]
signed short [ int ]
int
unsigned int
signed int
long
unsigned long
signed long [ int ]
注:
-
字符存储和表示的时候本质上使用的是 ASCII值,ASCII值是整数, 字符类型也 归类到整型家族。
-
[ ]表示里面的类型int可省略
- short等价于signed short int
- long 等价于singed long int
1.2.2 浮点数家族:
float
double
1.2.3 构造类型(自定义类型):
数组类型
结构体类型 struct
枚举类型 enum
联合类型 union
1.2.4 指针类型:
int* pi;
char* pc;
float* pf;
void* pv;
注:
- 指针类型决定接下来访问多少字节内容和类型
1.2.5 空类型
void 表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型。
如: void test( void )
{ }
2. 整型在内存中的存储
创建一个变量需要在内存中开辟空间,而空间的大小是由变量的类型决定的
我们知道 int a = 10; 需要为 a 提供四个字节的空间
那么 a 的内容在内存中如何储存呢?
为此我们引入了原码、反码、补码的概念
2.1原码、反码、补码
整数在计算机中有三种二进制表示方法:原码、反码和补码
三种方法均由符号位和数值位组成
第一位为 符号位,其余位为 数值位
符号位中 0 表示''正'',1 表示"负"
正数的原、反、补码都相同
负数的三种表示方法各不相同
原码
符号位为 ' 1 ' ,其余位和正数相同
反码
原码的符号位不变,其余位按位取反
补码
反码+1
2.2 练习
1.
#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;
}
详细讲解我放到上一篇中了,有兴趣的可以看一下
2.
unsigned int i;
for(i = 9; i >= 0; i--)
{
printf("%u\n",i);
}
结果是:结果进入死循环
前面输出9 8 7 ...0 我们都能理解,但是后面为什么会出现这种情况,让我们来逐层分析 :
当i=0后,i--后为-1
与0比较时自动类型转换,0和-1都被看做无符号整型
第一位不再看作是符号位
但-1 的补码仍为11111111 11111111 11111111 11111111
于是编译器将它看作4,294,967,295(十进制)
因此i > 0,程序继续运行,进入循环
3.
#include <stdio.h>
unsigned char i = 0;
int main()
{
for(i = 0;i<=255;i++)
{
printf("hello world\n");
}
return 0;
}
程序的结果仍为死循环,这是为什么?
我们知道无符号的char类型占一个字节,取值范围是0~255,
当i <= 255时,程序可以正常运行。
但是当 i = 255后,循环进行一次后 i++ ,i变成了256
256
补码:0001 0000 0000
但是 i 只能存放8个二进制位,所以 i 就变成 0000 0000,即 0
程序进入死循环
3. 浮点型在内存中的存储
3.1浮点数存储规则
- (-1)^S * M * 2^E
- (-1)^S表示符号位,当S=0,V为正数;当S=1,V为负数。
- M表示有效数字,大于等于1,小于2。
- 2^E表示指数位。
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M
指数 E 的计算值减去 127 (或 1023 ),得到真实值,再将有效数字M 前加上第一位的 1 。比如:0.5 ( 1/2 )的二进制形式为 0.1 ,由于规定正数部分必须为 1 ,即将小数点右移 1 位,则为1.0*2^(-1) ,其阶码为 -1+127=126 ,表示为01111110 ,而尾数 1.0 去掉整数部分为 0 ,补齐 0 到 23 位 00000000000000000000000 ,则其二进制表示形式为
0 01111110 00000000000000000000000
E全为0
浮点数的指数 E 等于 1-127 (或者 1-1023 )即为真实值,有效数字M 不再加上第一位的 1 ,而是还原为 0.xxxxxx 的小数。这样做是为了表示 ±0 ,以及接近于 0的很小的数字
- E为-127说明真实值是一个无限接近零的数(无穷小)
E全为1
如果有效数字 M 全为 0 ,表示 ± 无穷大(正负取决于符号位 s )
3.2 练习
#include <stdio.h>
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;
}
结果为:
第一个*pFloat的值为:0.000000的原因如下:
int n = 9;00000000 00000000 00000000 00001001float* pFloat = (float*)&n;将n 的地址看做float型的地址并赋给pFloat根据浮点数的存储规则,S=0E全为0,E=1-127M=0.0000000 00000000 00001001浮点数形式:(-1)^0*0.0000000 00000000 00001001*2^E结果为0.000000(只能打印小数点后六位)
第二个num的值为:1091567616的原因如下:
*pFloat = 9.0;将9.0按浮点数类型存放到n中9.0转换成二进制:1001.0标准格式:(-1)^0*1.001*2^3S=0M=1.001E=3 加上中间值127后 E=130在内存中实际的存储二进制码是0 10000010 00100000000000000000000输出格式为 %d ,按十进制打印即为1,091,567,616