一、计算机中的数据存储
【1】单位换算
1bit ----->可以存下一个二进制数
1Byte = 8bit
1KB = 1024Byte
1MB = 1024KB
1GB = 1024MB
1TB = 1024GB
【2】进制转换
二进制 | 八进制 | 十进制 | 十六进制 | |
基数 | 2 | 8 | 10 | 16 |
数码 | 0、1 | 0-7 | 0-9 | 0-9、A-F |
位权 | 从右向左数从 2^0、2^1、2^2、2^3···· | 8^0、8^1、8^2、8^3···· | 10^0、10^1、10^2、10^3···· | 16^0、16^1、16^2、16^3···· |
前导符 | 0b | 0 | 0x |
十进制与二进制转换
- 十进制转二进制:
- 整数部分:用被除数反复除以 2,除第一次外,每次除以 2 均取前一次商的整数部分作被除数并依次记下每次的余数。另外,所得到的商的最后一位余数是所求二进制数的最高位。
- 小数部分:采用连续乘以基数 2,并依次取出的整数部分,直至结果的小数部分为 0 为止,故该法称 “乘基取整法”。
- 二进制转十进制:从右往左依次用二进制位上的数字乘以的相应位数次幂(幂次从 0 开始),然后将各个结果相加。
十进制与八进制转换
- 十进制转八进制:用十进制数除以 8,取余数,然后将商继续除以 8,直到商为 0。最后将所有余数倒序排列,得到的就是八进制数。
- 八进制转十进制:从右往左依次用八进制位上的数字乘以的相应位数次幂(幂次从 0 开始),然后将各个结果相加。
十进制与十六进制转换
- 十进制转十六进制:用十进制数除以 16,取余数,然后将商继续除以 16,直到商为 0。十六进制中用 A、B、C、D、E、F 分别表示 10、11、12、13、14、15。最后将所有余数倒序排列,得到十六进制数。
- 十六进制转十进制:从右往左依次用十六进制位上的数字乘以的相应位数次幂(幂次从 0 开始),然后将各个结果相加。
二进制与八进制转换
- 二进制转八进制:从后往前每三位一组,缺位处用 0 填补,然后按十进制方法进行转化,最后将结果按从下往上的顺序书写。
- 八进制转二进制:从后往前每一位按十进制转化方式转化为三位二进制数,缺位处用 0 填补。
二进制与十六进制转换
- 二进制转十六进制:从后往前每四位一组,缺位处用 0 填补,然后按十进制方法进行转化,最后将结果按从下往上的顺序书写。
- 十六进制转二进制:从后往前每一位按十进制转化方式转化为四位二进制数,缺位处用 0 填补。
相关视频
二、数据类型
三、基本数据类型
【1】整型
用于存储整型数据:1、2 、3、4····
int | long(int) | long long (int) | short(int) | |
大小 | 4Byte | 32位占4Byte 64位占8Byte | 8Byte | 2Byte |
占位符/格式符 | %d | %ld | %ld | %d |
【2】浮点型
用于存储浮点型数据:3.14、0.98
浮点型数据在计算机中存储的是近似值
float | double | |
大小 | 4Byte | 8Byte |
占位符 | %f | %lf |
【3】字符型
用于存储字符类型数据:'a'、'0'(字符0)
字符类型数据指的是使用''引起来的单个字符
字符类型数据在计算机中实际是以ASCII码形式存储的
char | |
大小 | 1Byte |
占位符 | %c ---->用于字符格式 %d ---->用于ASCII码 |
【4】布尔型
特殊类型,该型的数据类型只有两个:true和false,也可以是0和1
bool | |
大小 | 1Byte |
占位符 | %d |
四、常量
常量就是程序运行过程中值不能修改的量
常量通常作为右值
【1】整型常量
整数1、2、3、4
输出格式符%d、%ld
在gcc环境下,默认常量为int类型
【2】浮点型常量
浮点数3.14、0.98
输出格式符%f、%lf 浮点型存储的是近似值
【3】字符型常量
由单引号引起来的单个字符叫字符型常量
'0'、'\n'·····
输出格式符%c/%d ----->%c输出字符格式、%d输出整形格式
【4】字符串常量
由双引号引起来的一个或多个字符叫字符串常量
"0"、"a"、"hello world"······
只存在字符串常量不存在字符串类型,C语言中不直接支持字符串类型
格式符/占位符:%s
五、宏定义
宏定义是一个简单的替换
宏定义的位置:
一般在头文件下方,主函数上方
宏替换发生在编译的预处理阶段
宏名一般大写(为了和变量做区分)
【1】无参宏
i)格式
#define 宏名 宏体
ii)替换阶段和过程
宏定义的替换发生在预处理阶段
宏定义只做简单的替换,宏定义的过程中没有运算
运行结果:
【2】带参宏
#define 宏名(参数1,参数2,参数3,····) 宏体
一般情况下,带参宏的宏体都是对参数相关的操作
运行结果:
六、变量
【1】定义格式
程序运行过程中可以修改的量,可以做右值也可以做左值。
存储类型 数据类型 变量名;
【2】存储类型
auto | 自动类型,默认是auto类型 |
extern | 外部类型,表示从外部引入的变量 |
static | 静态变量 |
const | 定义常量,const修饰的变量值不能更改 |
register | 寄存器类型,表示将变量定义到寄存器中,好处提高效率 |
volatile | 每次从内存中取该变量的值 |
【3】变量的初始化和赋值
变量名在C语言中是一个标识符,要符合标识符的命名规范:
1.由数字、字母和下划线构成
2.不能以数字开头
3.严格区分大小写
4.不能和C语言的32个关键字重复(不需要记关键字,只要代码发生高亮改名即可)
初始化:定义变量的同时给变量值叫做初始化
赋值:已有变量,使用=运算符给变量值叫赋值
变量不初始化默认是随机值,如果实在不知道给变量什么值直接赋值为0即可。
#include <stdio.h>
int main(int argc, const char *argv[])
{
//定义整形变量
int num1=90; //定义了一个整形变量num1并初始化为90
int num2; //定义了一个整形变量num2,没有初始化,默认是随机值
//使用已有的变量num1给num2变量赋值
num2 = num1; //赋值的过程是:等号右边的值赋值给等号左边的变量
//使用常量给变量赋值
num2 = 12;
printf("%d\t%d\n",num1,num2);
//定义浮点型变量
float f1 = 3.999999;
float f2;
f2 = f1; //使用已有的浮点型变量给新的浮点型变量赋值
char a = num1; //使用已有的整形变量给char类型的变量赋值
char a2 = 'A';
a = '0';
//使用浮点型变量给int类型的变量初始化
int num3 = f1;
printf("num3=%d\n",num3); //3
return 0;
}
【4】强制类型转换
i)隐式的强制类型转换
看不见数据强转的过程,强转过程自动发生
#include <stdio.h>
int main(int argc, const char *argv[])
{
float a = 0.9998;
int num1 = a; //发生隐式的强制类型转换,由浮点型转换成int型直接发生数据截取
printf("%d\n",num1);
return 0;
}
ii)显式的强制类型转换
看得见数据强转的过程
#include <stdio.h>
int main(int argc, const char *argv[])
{
float a = 0.9998;
int num1 = a; //发生隐式的强制类型转换,由浮点型转换成int型直接发生数据截取
printf("%d\n",num1);
//显式的强制类型转换
num1 = (int)a; //将float类型的a的强转成int后的结果赋值给num1
printf("%d\n",num1);
//printf("%d\n",a); 不叫强制类型转换,只是用%d整形格式符取float类型的数据
return 0;
}
iii)大数据类型向小数据类型强转
大的数据类型向小的数据类型强转是不安全的,因为小的数据类型没有足够的空间存下原有的数据,会发生数据的截取(能存多少存多少)
小的数据类型向大的数据类型强转是安全的。
#include <stdio.h>
int main(int argc, const char *argv[])
{
//大的向小的强转
int a = 0X0FFFFFFF;
printf("%d\n",a); //268435455
short num = (short)a;
printf("%d\n",num); //-1
//小的向大的强转
short num2 = 0XFFFF;
printf("%d\n",num2); //-1
int num3 = (int)num2;
printf("%d\n",num3); //-1
return 0;
}
iiii)有符号数和无符号数之间的强转
如果有符号数和无符号数一起参与运算,默认强转成无符号数。
【5】有符号数和无符号数
默认定义的都是有符号数
如果想要定义无符号数,需要使用unsigned
signed int a; //定义了有符号int类型的变量a
unsigned int b; //定义了一个无符号int类型的变量b
【6】原码、反码和补码
原码是给人看的
反码是原码转补码的中间格式
计算机中存储的全是补码,计算机中只有加法器,没有减法器
i)无符号数
原码就是二进制表示形式
原码、反码和补码都是同一个
无符号数14----->1110(原反补)
ii)有符号数
有符号数的最高位表示符号位
0正1负
有符号正数:
原码、反码和补码一致
有符号负数:
原码:数据的二进制形式
反码:除符号位外其他位取反
补码:反码+1
【7】变量的取值范围
所有有符号负数的最小值都是最高位为1其他位为0,并且1既是数据位也是符号位
以有符号的char类型为例,char占1Byte
正0:0000 0000
负0:1000 0000 ------> 反:1111 1111 ----> 补:1000 0000 ----->此时1既是符号位也是数据位,1000 0000就变成了-128的补码
(-128只有补码,推不出反码和原码)
新的有符号char的取值范围,使用补码表示:
1000 0000 ----- 0111 1111 ===> [-128,127] ==>[-2^7,2^7-1]
以有符号的int为例,int占4Byte
1000 0000 0000 0000 0000 0000 0000 0000 ---- 0x7FFFFFFF ===>[-2^31,2^31-1]
以有符号的short为例,short占2Byte
1000 0000 0000 0000 ----> 0x7F FF ===>[-2^15,2^15-1]
【8】计算机中数据存取的问题
计算机中数据存储都是以补码的格式存储的
存数据时,看数据的正负(看最高一位的符号位)
取数据时,看数据类型(看signed和unsigned)
#include <stdio.h>
int main(int argc, const char *argv[])
{
unsigned int a = -23;
//存看正负:-23
//原:1000 0 0 0 0 0 0001 0111
//反:0xFF FF FF 1110 1000
//补:0xFF FF FF 1110 1001
printf("%u\n",a); //%u输出无符号数
//取以%u取:无符号数
unsigned int num1 = -49;
//存看正负:-49
//原:0X80 00 00 0011 0001
//反:0XFF FF FF 1100 1110
//补:0xFF FF FF 1100 F
printf("%u\n",num1);
printf("%d\n",num1);
//大的向小的强转
int a1 = 0X0FFFFFFF;
//最高位0正数:0X0F FF FF FF
short num = (short)a1; //0X FF FF
//补:0XFF FF
//反:0XFF FE 1111 1111 1111 1110
//原:0x80 01 1000 0000 0000 0001
printf("%d\n",num); //-1
return 0;
}
练习:
1.求原码、反码和补码:
a:18
原码:0010010
反码:0010010
补码:0010010
b:-93
原码:10011101
反码:11100010
补码:10011110
c:-106
原码:11101010
反码:10010101
补码:10010110
2.求数据取出的值
unsigned int a = -9;
unsigned int a1 = -231;
unsigned short a2 = -16;
3.求NUM的值
#define N 12
#define M N*2+1
#define NUM M*M+N/3+(M*N)/2
//NUM运算过程:NUM=12*2+1*12*2+1+12/3+(12*2+1*12)/2