使用数据的不同类型的目的:合理利用空间
计算机存储的是二进制,是一位二进制只能存放0或1,内存:1bit
1字节 == 8b(八位二进制),范围:0000 0000 ~1111 1111
4B等于4个字节
知识点一:常用关键字
------------------------------------在32位平台下---------------------------------------
| 关键字 | 类型 | 所占的空间 |
|---|---|---|
| char | 字符串类型 | 占1字节空间(8位二进制位) |
| short | 短整型 | 占2字节空间(16位二进制位) |
| int | 整型 | 占4个字节空间(32位二进制) |
| long | 长整型 | 占4个字节空间(32位二进制)(在64为平台下占8个字节) |
| long long | 长长整型 | 占8字节 |
| float | 单精度浮点数 | 占4个字节空间(32为二进制)(6-7位有效位,指数-37到38) |
| double | 双精度浮点数 | 占8个字节空间(64为二进制)(15-16位有效位,指数-307到308) |
字符型
#include<stdio.h> //输出函数等需要的头文件
int main()
{
char a = 'aaaaa'; //定义字符 //字符单引号,字符串双引号,字符串需要借助数组实现
printf("%d\n",a); //字符%d输出,按照ASCII码表输入对应字符整数
printf("%c\n",a); //字符%c输出,则输出字符,%s,输入字符串
return 0;
}
整型
#include<stdio.h>
int main()
{
int a = 123; //定义整型
short int b = 456; //定义短整型
long c = 789; //定义长整型
long long d = 1243543511111111; //定义长长整型
printf("%d,%hd,%lu,%lld",a,b,c,d); //输出数据,123,456,789,1243543511111111
return 0;
}
实型(浮点型)
赋值语句中若涉及到浮点数时注意两边类型尽量保持一致
浮点数赋值,若赋值右边没有加 f 默认是 double 类型(占8个字节)
指数形式:123e3(123*10的三次方)
#include<stdio.h>
int main(int argc,char *argv[])
{
//赋值语句的 = 两边的类型尽量保持一致
float f = 3.14f;
double d = 3.14;
printf("sizeof(3.14) = %d\n",sizeof(3.14)); //8
//不以f结尾的 实型常量 为double类型
printf("sizeof(3.14) = %d\n",sizeof(3.14f)); //4
//以f结尾的 实型常量 为float类型
printf("f = %f\n",f);
printf("d = %lf\n",d);
scanf("%f",&f);
scanf("%lf",&d);
return 0;
}
#include<stdio.h>
int main()
{
float a = 3.14; //定义float类型
double b = 4.311111123456789; //定义double类型
//在输出时%f可以输出float和double,但scanf输入时不能通用
printf("%f,%f\n",a,b); //3.140000,4.311111
//如果输出位数较多,得限制位数才可以输出完整
printf("%.6f,%.15lf",a,b); //3.140000,4.311111123456789
//如果越界,越界的数字是随机数
return 0;
}
测试类型所占空间
sizeof:测试类型的长度(所占的空间)
#include<stdio.h> //输出函数等需要的头文件
int main(int argc,char *argv[])
{
printf("sizeof(int) = %d\n",sizeof(int)); //4
printf("sizeof(float) = %d\n",sizeof(float)); //4
printf("sizeof(doublt) = %d\n",sizeof(double)); //8
printf("sizeof(long) = %d\n",sizeof(long)); //4
printf("sizeof(short) = %d\n",sizeof(short)); //2
printf("sizeof(char) = %d\n",sizeof(char)); //1
return 0;
}
布尔型
#include<stdio.h> //输出函数等需要的头文件
#include<stdbool.h> //布尔类型头文件
int main()
{
bool a = 1; //定义布尔类型
printf("%d\n",a); //1
return 0;
}
知识点二:unsigned 和 signed
1、无符号数:unsigned
数据没有符号位,自身所有二进制位都是数据位
例:unsigned char 0000 0000 ~ 1111 1111
2、有符号数:signed(默认省略)
二进制最高位为 1 表示负数,最高位为 0 表示正数,其他位为数据位
负数:1xxx xxxx 正数:0xxx xxxx(x:0或1)
#include<stdio.h>
int main(int argc,char *argv[])
{
//定义一个有符号int
//signed int num1 = 10;
int num2 = 10; //有符号(signed)默认省略
//unsigned 表示无符号数 不能省略
unsigned num3 = 10;
return 0;
}
知识点三:结构体 struct 和 共用体 union
1、struct:结构体中成员拥有独立空间
struct data1
{
char a;
int b;
shuot c;
};
a,b,c就是结构体dat1中的成员
2、union:共用体中成员共享同一部分空间
union data2
{
char a;
short b;
int c;
};
知识点四:enum 和 void
1、enum:枚举
将变量要赋值的值一一列举出来
enum BOOL{false,ture};
//括号里面的是可以赋给变量的值,赋的值只能括号里面有的
enum BOOL bool = false;
2、void:无类型
不能用void定义变量
知识点五:其他关键字
| 关键字 | 含义 | 关键字 | 含义 |
|---|---|---|---|
| auto | 自动类型 | register | 寄存器变量 |
| static | 静态变量 | const | 只读 |
sizeof | 测类型大小 | typedef | 为已有的类型重新取别名 |
| volatile | 防止编译器优化 | extern | 外部的意思,一般用于函数和全局变量的声明 |
1、register:寄存器变量

总结:
-
如果没有显示表明 register ,类似 int num,如果被高频使用系统也会放入寄存器中
-
register int num; //显示表明将num放入寄存器
-
寄存器的变量不能取地址
#include<stdio.h>
int main(int argc,char *argv[])
{
register int num = 10;
//%p输出地址
printf("%p\n",&num); //错误 不能对寄存器变量取地址
return 0;
}
2、typedef:为已有类型取别名
#include<stdio.h>
typedef int INT32; //取别名
int main(int argc,char *argv[])
{
int num1 = 10;
INT32 num2 = 34;
printf("num1 = %d\n",num1); //20
printf("num2 = %d\n",num2); //34
return 0;
}
3、volatile:防止编译器优化
作用:强制访问内存操作
这个关键字声明的变量,编译器对访问该变量的代码就不再进行优化,从而可以提供对特殊地址的稳定访问
volatile int i=10;
int a = i;
...
// 其他代码,并未明确告诉编译器,对 i 进行过操作
int b = i;
volatile 指出 i 是随时可能发生变化的,每次使用它的时候必须从 i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在 b 中
优化做法(禁止):由于编译器发现两次从 i读数据的代码之间的代码没有对 i 进行过操作,它会自动把上次读的数据放在 b 中。而不是重新从 i 里面读
知识点六:常量与变量
1、常量
值不能被修改(但不能反过来说:值不能被修改是常量)
例:10、20、4.14、'a'、"abcd"
2、变量
-
系统根据变量的类型开辟对应的空间,其值可以被修改
-
变量名代表空间的内容 -
操作变量 就是对 空间内容的操作
-
变量的命名规制:由数值、字符、下划线组成但是不能以数字开头
int num = 10; //变量名 num 代表空间内容 10,4B字节空间
知识点七:进制
进制类型及输出方法
输出时在 % 后加 # 表示输出进制的前缀
不同进制仅仅只是数据的表现形式不会修改数据本身
#include<stdio.h>
int main(int argc,char *argv[])
{
int num = 100;
//加个#号就是输出进制的前缀
printf("十进制:num = %d\n",num); //十进制输出 %d %u %ld %lu
printf("八进制:num = %#o\n",num); //八进制输出 %o 以0开头
printf("十六进制:num = %#x\n",num); //十六进制输出 %x 以0x开头
printf("十六进制:num = %#X\n",num); //十六进制输出,但输出的十六进制字母X为大写
return 0;
}
//十进制:num = 100
//八进制:num = 0144
//十六进制:num = 0x64
进制转换
需要分组的只有八进制和十六进制,八进制3个数字为一组,十六进制4个数字为一组
对于整数, 有四种表示方式:
二进制:0,1 ,满 2 进 1,以 0b 或 0B 开头
十进制:0-9 ,满 10 进 1
八进制:0-7 ,满 8 进 1,以数字 0 开头表示
十六进制:0-9 及 A(10) - F(15),满 16 进 1,以 0x 或 0X 开头表示。此处的 A-F 不区分大小写
方法:8421法
二进制转八进制
三位为一组,一组按1,2,4分
0 0 1 1 0 1 0 0
4 2 1 4 2 1
————————————
从左往右,三位一组,第一组三位中二进制为1的相加得八进制的个位,第二组三位中二进制为1的相加得八进制的十位,如果有第三组三位数则为1相加则为八进制的百位,以此类推
第一个三位二进制,1 0 0 则 421,为1的只有4,则八进制个位数为4
第二个三位二进制,1 1 0 则 421,为1的有4 和 2,则八进制十位数为4 + 2 = 6
则八进制为:(0)64
八进制转二进制
八进制拆开单独数字,一个数字对应三位 再按1,2,4分解
64 --》分为两组(三位一组),从左到右,第一组为4,第二组为6,6又分为4 + 2,有对应数字的二进制为1,没有为0
4 2 1 4 2 1
1 1 0 1 0 0
位数不足补零 0011 0100
二进制转十进制
直接按1、2、4、8.....分,二进制为1的数字相加
0 0 0 1 0 1 0 1
16 8 4 2 1
————————————
16+4+1 = 21
十进制转二进制
十进制拆分,1,2,4,8........组合的数,无需分组
21 = 16 + 4 + 1
16 8 4 2 1
——————
1 0 1 0 1 位数不足补零,0001 0101
二进制转十六进制
四位为一组,一组按1,2,4,8分
0 0 1 1 0 1 0 0
8 4 2 1 8 4 2 1
————————
从左往右,四位一组,第一组四位中二进制为1的相加得十六进制的个位,第二组四位中二进制为1的相加得十六进制的十位,第三组四位中二进制为1的相加得十六进制的百位,以此类推
第一个四位二进制,0 1 0 0 则 8421,为1的只有4,则八进制个位数为4
第二个四位二进制,0 0 1 1 则 8421,为1的有1 和 2,则八进制十位数为1 + 2 = 3
则十六进制为:0x34
十六进制转二进制
十六进制数分开单个数字,一个数字对应四位,并拆分 1,2,4,8....数组成
0x2A =》分为两组(四位一组),从左到右,第一组为A,A又分为8 + 2,第二组为2,有对应数字的二进制为1,没有为0
8 4 2 1 8 4 2 1
————————————————
0 0 1 0 1 0 1 0
八进制转十进制
八转二,二转十
十进制转八进制
十转二,二转八
八进制转十六进制
八转二,二转十六
十六进制转八进制
十六转二,二转八
十进制转十六进制
十转二,二转十六
十六进制转十进制
十六转二,二转十
知识点八:(整型变量操作)取值、赋值
void test04()
{
//局部变量不初始化 内容随机
//int num;
int data = 0;
int num = 0;
printf("num = %d\n",num); //读 取值,0
num = 100; //写 赋值
printf("num = %d\n",num); //100
data = num; //num读 data写
printf("data = %d\n",data); //100
//获取键盘输入
printf("请输入一个int数据:");
scanf("%d", &data); //&data 代表是data对应空间的起始地址
printf("data = %d\n",data);
}
知识点九:数据输出
| 符号 | 含义 |
|---|---|
| %d | 十进制有符号整数输出 |
| %u | 十进制无符号整数输出 |
| %ld | 有符号长整型输出 |
| %lu | 无符号long数据输出 |
| %hd/%hu | 有/无符号short数据输出 |
| %o | 以八进制表示的整数输出 |
| %x | 以十六进制表示的整数输出 |
| %f | float型浮点数输出 |
| %lf | double型浮点数输出 |
| %e | 指数形式的浮点数输出 |
| %c | 单个字符输出 |
| %s | 字符串输出 |
| %p | 指针的值输出 |
输出的格式
%3d %03d %-3d %5.2f
%3d:要求宽度为3位,如果不足3位,前面空格补齐,如果足够3位,此语句无效
%03d:要求宽度为3位,如果不足3位,前面0补齐,如果足够3位,此语句无效
%-3d:要求宽度为3位,如果不足3位,后面空格补齐,如果足够3位,此语句无效
%5.2f:总宽度为5,.2表示:小数位保留2位
但不能写 %-03d
int main(int argc,char *argv[])
{
printf("##############\n");
//%5d 表示占5个终端位宽 右对齐
printf("##%5d##\n",123); //### 123###
//%‐5d 表示占5个终端位宽 左对齐
printf("##%‐5d##\n",123); //###123 ###
//%05d 表示占5个终端位宽 右对齐 不足补0
printf("##%05d##\n",123); //###00123###
//千万不能写 %‐05d
//printf("##%‐05d##\n",123);
//%5.2f 5表示总位宽为5 .2表示小数位保留2位
printf("##%5.2f##\n", 3.14159f); //### 3.14###
}
实型 常量
void test06()
{
//赋值语句 = 两边的类型 尽量保证一致
float f = 3.14f;//有没有问题
double d = 3.14;
//不以f结尾的 实型常量 为double类型
printf("sizeof(3.14) =%d\n",sizeof(3.14)); //8
//以f结尾的 实型常量 为float类型
printf("sizeof(3.14f) =%d\n",sizeof(3.14f)); //4
//%f 输出 float数据
printf("f = %f\n",f);
//%lf 输出 double数据
printf("d = %lf\n", d);
scanf("%f", &f);
scanf("%lf", &d);
}
知识点十:字符(char)常量与变量
用 ' ' 包裹字符
%c 输出输出字符,用 %d 输出字符的ascii值
本质:在内存保存的是字符对应的ASCII码值,字符与对应的ASCII值完全等价
使用 scanf 键盘输入字符用 %c 只能提取一个字符
#include<stdio.h>
void test08()
{
//%c 输出的字符
//printf("%c\n",'a');
//字符变量
char ch = 'a'; //ch 存储的是 ‘a’的ASCII值
printf("ch = %c\n",ch);
//%d 输出的字符的ASCII值11
printf("ch = %d\n",ch);
//'a' 单引号 表示的取 字符的ASCII
//'a' == 97是完全等价
ch = 97;
printf("ch = %c\n",ch);
//%d 输出的字符的ASCII值
printf("ch = %d\n",ch);
ch = ch+1;
printf("ch = %c\n",ch);
//%d 输出的字符的ASCII值
printf("ch = %d\n",ch);
}
//字符获取键盘输入
void test09()
{
char ch;
printf("请输入一个字符:");
//scanf中%c只能提取一个字符
//scanf("%c", &ch);
ch = getchar(); //获取一个字符
printf("ch = %c\n",ch); //a
printf("ch = %d\n",ch); //97
return 0;
}
知识点十一:字符串
用 " " 包裹字符,默认结尾自动添加\0 结尾(占一个字节),只要遇到 \0 就结束
描述:'a'和"a"的区别
'a'字符 占1字节,"a"字符串 占2字节(多'\0')
int main(int argc,char *argv[])
{
//%s 就是输出字符串
//''取的是字符的ASCII值 ""取的是字符串的首元素的地址
//%s 从字符串的首元素 逐个字符输出 遇到'\0' (重要)
printf("%s\n", "hello"); //hello
//系统会在字符串末尾自动添加一个结束字符'\0'
printf("%d\n",sizeof("hello")); //6
printf("%s\n","hello world"); //hello world
printf("%s\n","hello\0world"); //hello,\0:字符串结束符
printf("##%s##\n","\0hello\0world"); //###
}
知识点十二:转义字符
| 字符形式 | 功能 | 字符形式 | 功能 |
|---|---|---|---|
| \n | 回车换行 | \\ | 一个反斜杠字符(\) |
| \t | 将当前位置移到下一个tab位置 | \' | 一个单引号(') |
| \v | 当前位置移到下一个垂直制表对齐点 | \" | 一个双引号(") |
| \r | 回车符 | \ddd | 三位八进制数代表一个ASCII字符 |
| \f | 换页符 | \xhh | 二位十六进制代表一个ASCII字符 |
| \b | 将当前位置后退一个字符 | \0 | 空值,其ASCII码值为0 |