文章目录
1 数据类型
告诉编译器这个对象(变量)在内存中需要多大的空间
装数的盒子:
盒子多大 ——> 依据要存的数据 ——> 有各类不同的盒子选择
数据类型 变量名
int 类型 在内存中占 4字节
short 类型 2字节
long 类型 在windows 4字节,linux 32位4字节,64位8字节
char 类型 1字节
float 类型 4字节,一般用来存小数
double 类型 8字节,用来存小数
例子:
int a: //在内存中定义了一个变量a,占int类型大小4字节
char b: //在内存中定义了一个变量b,占char类型大小1字节
char类型是最小整型单位
2 常量和变量
2.1 常量
在程序运行过程中,其值不能被改变的量
常量一般出现在表达式或赋值语句中
整型常量 100,200,-100,0
实型常量 3.14 , 0.125,-3.123
字符型常量 ‘a’,‘b’,‘1’,‘\n’
字符串常量 “a”,“ab”,“12356”
2.2 变量
定义:
在程序运行过程中,其值可以改变
变量在使用前必须先定义,定义变量前必须有相应的数据类型
变量特点:
变量在编译时为其分配相应的内存空间
可以通过其名字和地址访问相应内存
声明、定义、赋值这个三个词的含义和关系:
声明变量不建立存储空间,如:extern int a;
定义变量建立存储空间,如:int b;
#include <stdio.h>
int main()
{
//extern 关键字只做声明,不能做任何定义,后面还会学习,这里先了解
//声明一个变量a,a在这里没有建立存储空间
extern int a;
a = 10; //err, 没有空间,就不可以赋值
int b = 10; //定义一个变量b,b的类型为int,b赋值为10
return 0;
}
声明不开辟空间
定义开辟空间
开辟了空间才可以赋值
2.3 案例介绍
#include <stdio.h>
#define MAX 10 //声明了一个常量,名字叫MAX,值是10,常量的值一旦初始化不可改
int main()
{
int a; //定义了一个变量,其类型为int,名字叫a
const int b = 10; //定义一个const常量,名为叫b,值为10
//b = 11; //err,常量的值不能改变
//MAX = 100; //err,常量的值不能改变
a = MAX;//将abc的值设置为MAX的值
a = 123;
printf("%d\n", a); //打印变量a的值
return 0;
}
3 进制的概念
3.1 C语言如何表示相应进制数
二进制 C语言不能直接书写二进制数
八进制 以数字0开头,如0123
十六进制 以0x开头,如0x123
3.2 进制的书写和打印
#include <stdio.h>
int main()
{
int a = 123; //十进制方式赋值
int b = 0123; //八进制方式赋值, 以数字0开头
int c = 0xABC; //十六进制方式赋值
//如果在printf中输出一个十进制数那么用%d,八进制用%o,十六进制是%x
printf("十进制:%d\n",a );
printf("八进制:%o\n", b); //%o,为字母o,不是数字
printf("十六进制:%x\n", c);
return 0;
}
数在计算机存的内容没有改变,打印时只是输出的形式改变而已
原理:存储的是补码,输出的时候看规则,一段010…01的二进制补码,看如果要输出10进制,就按十进制解析
int main()
{
int b = 056;
//
printf("a=%o\n", b);//56
printf("a=%X\n", b);//2E
printf("a=%d\n", b);//46
system("pause");
return 0;
}
3.3 进制互转
二进制与十进制互转:
二进制与八进制互转:
八进制的数和二进制数可以按位对应(八进制一位对应二进制三位),因此常应用在计算机语言中。
4 整型变量
4.1 划分
整型分为有符号(signed)和无符号数(unsigned)
举例:
signed char 8位:
1位符号位(1:负数;0:正数) + 7位数据位
unsigned char 8位:
8位数据位
同理:int 有符号:1位+31位 无符号:32位
特点:
unsigned为非负数,用此类型可以增加数据长度
默认是有符号:char = signed char
4.2 范围
以char类型为例:
signed char:8位
1开头负数: 10000000-11111111 -0 ~ -127
0开头正数: 00000000-01111111 +0 ~ +127
规定 -0 表示为 -128
范围为:-128 ~ +127(-2^7 -> 2^7-1)
unsigned char:
00000000-11111111
范围为:0 ~ 255
有符号数和无符号数能够表示数的个数相同,只是表示数的范围不同
short
signed short (-2^15 -> 2^15-1)
unsigned short (0 -> 2^16-1)
int
signed int (-2^31 -> 2^31-1)
unsigned int (0 -> 2^32-1)
问题:数的溢出问题
char num = 127+2; 结果:-127
为什么是-127? ——> 原码、反码、补码
4.3 原码
数的最原始的二进制码
有符号:
+120:01111000
-23:10010111
关于负数的原码有两个问题:
1 负数原码计算问题
按照原码情况:
-1: 1000 0001
1: 0000 0001
1 + -1?
0000 0001
1000 0001
1000 0010 = -2 error
负数拿原码计算是错误的
2 负数原码表示问题
-0: 1000 0000
+0: 0000 0000
0的原码有两种状态
4.4 反码
正数的反码不变 ,负数的反码(符号位不变,其他位取反)
-0:1111 1111
+0:0000 0000
-1:1111 1110
+1:0000 0001
1 计算问题解决了
1 + -1 = 1111 1111 = -0
如果计算机用反码去存,负数运算结果正确
2 表示问题仍然有问题
-0:1111 1111
+0:0000 0000
但是 0的状态还是有两种
4.5 补码
正数的补码不变=原码=反码,负数的补码等于反码加1
-0: 0000 0000
+0: 0000 0000
-1: 1111 1111
+1: 0000 0001
1+ -1= 0
如果计算机用补码去存,负数运算结果是正确的,0的状态只有一种。
在计算机系统中,数值一律用补码来存储。
案例:
char num = 129;
printf(“num=%d\n”,num); //-127
原理:
输入(赋值时):存储补码
输出(打印时):显示数的原码
129的补码=原码为1000 0001
计算机打印时:取出1000 0001 翻译:
1:符号位1表示负数,负数要经过补码转反码转到原码
2: 补码1000 0001转为原码为1111 1111
3:显示原码:-127
tips:存数直接存补码,取数看二进制补码翻译成原码
补码转原码:
补码转反码:符号位不变,其他位取反
反码转原码:反码+1
无符号为非负数,所有的为原码=反码=补码
4.6 输出
打印格式 含义
%d 输出一个有符号的10进制int类型
%o(字母o) 输出8进制的int类型
%x 输出16进制的int类型,字母以小写输出
%X 输出16进制的int类型,字母以大写输出
%u 输出一个10进制的无符号数
%d 有符号打印int
%u 无符号打印int
%hd 有符号打印short
%hu 无符号打印short
%ld 有符号打印long
%lu 无符号打印long
#include <stdio.h>
int main()
{
//自动将int类型的10转为short类型
short a = 10;
int b = 10;
long c = 10l; //或者10L
//不写l会自动的将int转为long
long long d = 10ll; //或者10LL
printf("sizeof(a) = %u\n", sizeof(a));
printf("sizeof(b) = %u\n", sizeof(b));
printf("sizeof(c) = %u\n", sizeof(c));
printf("sizeof(c) = %u\n", sizeof(d));
printf("short a = %hd\n", a);
printf("int b = %d\n", b);
printf("long c = %ld\n", c);
printf("long long d = %lld\n", d);
//不加u会自动类型转换
unsigned short a2 = 20u;
unsigned int b2 = 20u;
unsigned long c2= 20ul;
unsigned long long d2 = 20ull;
printf("unsigned short a = %hu\n", a2);
printf("unsigned int b = %u\n", b2);
printf("unsigned long c = %lu\n", c2);
printf("unsigned long long d = %llu\n", d2);
return 0;
}
案例1:
思考题:
8位补码转32位原码的问题?
4.7 输入
情况1:
情况2:
4.8 内存所占字节
sizeof
short、int、long、long long
int main()
{
char a;
short b;
int c;
long d;
long long e;
//sizeof 用来测数据类型的大小
int len = sizeof(a);
printf("%d\n",len);
printf("%d\n",sizeof(a));
printf("%d\n", sizeof(b));
printf("%d\n", sizeof(c));
printf("long = %d\n", sizeof(d));
printf("%d\n", sizeof(e));
printf("%d\n", sizeof(int));
system("pause");
return 0;
}
5 字符型(本质是整型)
5.1 字符型本质
内存中不能直接存字符,只能存0101…01,存的是编码,ASCII码
字符变量实际上并不是把该字符本身放到变量的内存单元中去,而是将该字符对应的 ASCII 编码放到变量的存储单元中。char的本质就是一个1字节大小的整型。
字符'0' ascii值是48
字符'1' ascii值是49
'A' ascii值是65
'B' ascii值是66
'a' ascii值是97
'b' ascii值是98
存储和运算都是用的ASCII
5.2 ASCII码表
ASCII 码大致由以下两部分组成:
ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。
ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。数字 127 代表 Del 命令。
因为字符所对应的最大ascii值是127,所以用char类型就可以存得下所有的字符
5.3 字符变量的输入与输出
输入:scanf getchar
从键盘读取一个字符
int main()
{
char ch = 0;
scanf("%c",&ch);// ch = getchar();
printf("ch=%c\n",ch);
system("pause");
return 0;
}
从键盘读取两个字符
解决办法:
输出:printf putchar
#include <stdio.h>
int main()
{
char ch = 'a';
printf("sizeof(ch) = %u\n", sizeof(ch));
printf("ch[%%c] = %c\n", ch); //打印字符 putchar(ch);
printf("ch[%%d] = %d\n", ch); //打印‘a’ ASCII的值
char A = 'A';
char a = 'a';
printf("a = %d\n", a); //97
printf("A = %d\n", A); //65
printf("A = %c\n", 'a' - 32); //小写a转大写A
printf("a = %c\n", 'A' + 32); //大写A转小写a
ch = ' ';
printf("空字符:%d\n", ch); //空字符ASCII的值为32
printf("A = %c\n", 'a' - ' '); //小写a转大写A
printf("a = %c\n", 'A' + ' '); //大写A转小写a
return 0;
}
测试题1:
测试题2:
数字字符转为整数数字
测试题3:
大写字母与小写字母互转
5.4 转义字符
测试题1:
6 浮点型(实型)
浮点型变量分为两种:
单精度浮点数(float)
双精度浮点数(double)
但是double型变量所表示的浮点数比 float 型变量更精确。
float类型能够保证的精度是7位有效数字
double类型能够保证的精度是15位有效数字
int main()
{
//打印时,默认输出6位小数点
//float类型能够保证的精度是7位有效数字
//double类型能够保证的精度是15位有效数字
float a = 3.1415926456;
double b = 3.1415926456;
//输出.8表示保留8位小数
printf("a=%.8f\n",a);
printf("a=%.8lf\n", b);
system("pause");
return 0;
}
我们一般都用double
7 字符串
7.1 字符串常量
- 字符串是内存中一段连续的char空间,以’\0’(\0字符的ascii值是0)结尾。
- 字符串常量是由双引号括起来的字符序列,如“china”、“C program”,“$12.5”等都是合法的字符串常量。
字符串常量与字符常量的不同:
每个字符串的结尾,编译器会自动的添加一个结束标志位’\0’,即 “a” 包含两个字符’a’和’\0’。
tips:数字0 字符‘0’和\0的区别:
数字0 内存中存的是0
'0' 内存中存的是48
'\0' 内存中存的是0
'\0' == 0
打印字符串
printf("%s\n","hello");
8 printf函数
printf是输出一个字符串,putchar输出一个char。
8.1 printf格式字符
8.2 printf附加格式
int main()
{
//m.n m指的是宽度 n指的是小数点的位数
double a = 3.1415;
printf("%10.4lf\n",a);
int b = 10;
printf("%d\n", b);
printf("%5d\n", b);//占5位
printf("%-5d\n", b);//左对齐占5位
//printf("%0-5d\n", b); 左对齐和补0不能同时用
printf("%05d\n", b);//用0补全宽度不足的位
system("pause");
return 0;
}
9 类型限定符
10 类型转换
转换的方法有两种:
-
自动转换(隐式转换):遵循一定的规则,由编译系统自动完成。
-
强制类型转换:把表达式的运算结果强制转换成所需的数据类型。
原则:由低向高转
int main()
{
int a = 3;
double b = (double)a;//隐式转换
//类型的转换 所需要的类型和给的类型不匹配,需要转换
//强制转换 (需要转的类型)原来的数据类型
printf("%d\n",(int)3.14);
printf("%lf\n",(double)a);
system("pause");
return 0;
}