基本的内置数据类型
char 字符数据类型
short 短整型
int 整形
long 长整型
long long 更长的整形
float 单精度浮点数
double 双精度浮点数
类型的基本归类
整形家族
char
unsigned char
signed char
short
unsigned short [int]
signed short [int]
int
unsigned int
signed int
long
unsigned long [int]
signed
浮点型家族
float
double
构造类型-自定义类型
// 数组
//struct 结构体类型
// enum 枚举
// union 联合体
//
指针类型
//
空类型
//void
//函数返回类型 void test();
//函数参数 void test(void);
//指针 void* p;
在这里主要介绍整型类和浮点类
C语言标准并没有规定
cahr 到底是 signed char
还是 unsigned char 这取决于 编译器
int 是 signed int 有符号 int
short 是 signed short 有符号 short
整数在内存中的存储形式
数据在内存中以2进制的形式存储
对于整数来说:
整数二进制有3种表示形式:原码、反码、补码
正整数:原码、反码、补码相同
负整数:原码、反码、补码要进行计算的
按照数据的数值直接写出的二进制序列就是原码
原码的符号位不变,其他位按位取反,得到的就是反码
反码+1,得到的就是补码
补码
对于整形来说:数据存放内存中其实存放的是补码。
在计算机系统中,数值一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理; 同时,加法和减法也可以统一处理(CPU只有加法器)此外,补码与原码相互转换,其运算过程是相同的,不需要额外的硬件电路。
举例:
int main()
{
1 - 1;
1 + (-1);//cpu上只有加法器,除法也就是多模拟几次减法
//假如内存中存储的是原码
//000000000000000000000000000001 1
//100000000000000000000000000001 -1//二进制相加
//100000000000000000000000000010 -2
//补码
//100000000000000000000000000001 1 //正整数原返补码相同
//100000000000000000000000000001 -1//-1的原码
//111111111111111111111111111110 //-1的反码
//111111111111111111111111111111 //-1的补码
//000000000000000000000000000001
//111111111111111111111111111111
//1000000000000000000000000000000 //二进制进完最后一个1后丢失了只剩下32个0,为0
return 0;
}
按照上述提到的方法思路 补码减1得到反码,反码再按照符号位不变其他位按位取反得到原码
补码与原码相互转换,其运算过程是相同的
举例:
int main()
{
-1;
//100000000000000000000000000001 这是-1的原码
//111111111111111111111111111110 //-1 的反码
//111111111111111111111111111111 //-1 的补码
//100000000000000000000000000000 //-1 符号位不变其他位按位取反
//100000000000000000000000000001 //加1 得到原码
return 0;
}
大段 小端
什么是大端小端:
大端(存储)模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中;
小端(存储)模式,是指数据的低位保存在内存的低地址中,而数据的高位,,保存在内存的高地址中。
字节序:以一个字节为单位,字节的顺序
判断当前机器字节序
这里我们写一个代码来判断当前机器字节序
//一个整型在内存中占4个字节 用十六进制表示为00 00 00 01
//这时只要判断第一个字节放的是 00 或者 01 就可判断出是大端还是小端
//只访问第一个字节 要用到指针的类型 char * 一次访问一个字节
int check_sys()
{
int a = 1;
char * p = (char*)&a;//a是个int占4个字节 要强制类型转换成char类型
return *p;//返回1,表示小端,返回0表示大端
}
int main()
{
int ret = check_sys();
if (ret == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}
char类型变量的取值范围
内存中看到1后面7个0
10000000 //会被直接编译成-128
有符号的char取值范围:-128~127
无符号的char取值范围:0~255
练习
加深数据在内存中的存储理解,分析题目,实践出真知
#include <stdio.h>
int main()
{
char a = -1;//有符号的char
//100000000000000000000000000001 原码
//111111111111111111111111111110 反码
//111111111111111111111111111111 补码
//11111111 //认为高位是符号位,整数在内存中存储空间有限,发生截断
//111111111111111111111111111111 整型提升后的补码
signed char b = -1;//有符号的char
//11111111
//111111111111111111111111111111
unsigned char c = -1;//无符号char
//11111111 //没有符号位,无符号位整型提升高位补0
//000000000000000000000011111111
printf("a=%d,b=%d,c=%d", a, b, c);
//%d的形式打印,发生整型提升,整型提升看原符号位
return 0;
}
输出结果就为
2.
#include <stdio.h>
int main()
{
char a = -128;
//10000000
printf("%u\n", a);
//%u无符号位
//111111111111111111111111100000
return 0;
}
输出结果为
按照补码的形式进行运算,最后格式化成为有符号整数
int main()
{
int i = -20;
//100000000000000000000000010100
//111111111111111111111111101011
//111111111111111111111111101100
unsigned int j = 10;
//000000000000000000000000001010
printf("%d\n", i + j); //%d打印有符号数
//111111111111111111111111101100
//000000000000000000000000001010
//111111111111111111111111110110 //补码
//111111111111111111111111110101
//100000000000000000000000001010 //-10
return 0;
}
输出结果为
4.
unsigned int 无符号整型 >=0
int main()
{
unsigned int i;
for (i = 9; i >= 0; i--)//unsigned最小为0,判断部分为真一直循环
{
printf("%u\n", i);
}
return 0;
}
输出结果:一直循环
int main()
{
char a[1000];//char取值范围0~255
int i;
for (i = 0; i<1000; i++)
{
a[i] = -1 - i;
}
printf("%d", strlen(a));//strlen求长度遇见\0停止,\0 ASCLL码值为0
return 0;
}
输出结果: