目录
一、常量
(一) 定义
-
值不能被改变的量
-
千万不能反过来说:值不能修改就是常量,后面会提到const修饰的常变量
(二) 整型常量(整数)
-
在内存中以二进制形式存储
-
十进制整数后面加L/l 表示long int 型常量,往往用于函数调用
-
八进制、十进制、十六进制都是整型的输出形式
-
不同进制仅仅是数据的表现形式,不会修改数据本身
int num = 100;
//十进制 输出 %d %u %ld %lu
printf("十进制:num=%d\n", num); // 100
//八进制 输出 %o 以0开头
printf("八进制:num=%#o\n", num); // 0144
//十六进制 输出 %x 以0x开头
printf("十六进制:num=%#x\n", num); // 0x64
-
以八进制、十六进制输出十进制数时,在格式占位符中间添加#,以区分输出的结果进制类型。若不添加输出为100 、144、64,这样不能识别数据的进制类型;添加后输出为100、0144、0x64,这样的形式可以看出进制的区分。
(三) 实型常量(浮点型)
-
在内存中都是以指数形式存储
-
形式为数符+数字部分+指数部分
1、十进制小数形式
-
默认为double类型
-
实数后面加F/f 表示为单精度浮点数,不可以在整数后面加f
-
实数后面加L/l 表示为长双精度
-
小数形式输出默认精确到小数点后6位
2、指数形式(浮点形式)
// 赋值语句 = 两边的类型 尽量保证一致
float f = 3.14f;
double d = 3.14;
printf("%f\n", 12345f); // %f 输出 float数据
printf("d = %lf\n", d); // %lf 输出 double数据
printf("%f\n", 123.45e2); // e表示科学计数法的小数
printf("%0.8f\n", 123.45e2); // 0.8为域宽控制,规定小数位数,小数点后八位
printf("%2.3f", 123.456789);
// 对于整数部分,如果整数部分位数小于2位,则在前面补0;如果整数部分大于2位,则整数部分原样输出
// 规定小数位数保留3位,不足补0,超过就四舍五入
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);
(四) 字符常量
1、普通字符常量
-
单引号表示的是取字符的ASCII值
-
占一个字节
-
字符型在内存中是以ASCII码形式存储的
// ch 存储的是 ‘a’的ASCII值
char ch = 'a';
// 'a' == 97是完全等价
ch = 97;
printf("ch = %c\n",ch); // 'a'
printf("ch = %d\n",ch); // 以%d的格式输出'a'的ASCII值97
printf("%d\n",sizeof('a')); // 4字节 'a' == 97是一个整型常量,占四个字节
printf("%d\n",sizeof(char)); // 1 字节
- 注意:char ch = -10;针对这句代码,将-10赋值给字符常量ch。因为字符常量有符号范围为0~255,无符号范围为-128~127,这样赋值是没有错的,字符常量并不是只能赋值字符
- 重点在于ch的输出,当以%c格式输出时,会输出乱码。因为字符常量输出时需要对照ASCII表进行查找,但是ASCII表只有0~127的数值范围,所以是不能进行这样输出的
2、转义字符常量
- 以下四个选项中哪两个选项的结果相同?答:B、C
char ch = '\0';
printf("A:%d\n", '0'); // 48
printf("B:%d\n", '\0'); // 0 全部清空为0
printf("C:%d\n", 0); // 0
printf("D:%d\n", "0"); // 字符‘0’地址
\101 // 八进制101转化为十进制ASCII值65,代表字符"A"
\1234 // 转义字符只有前三个数字构成 4是单独的字符
\xAB // 以\x开头的十六进制转义字符
\x // x后面所有的数字
(五) 字符串常量
-
双引号取的是字符串的首元素的地址
-
系统自动加‘\0’作为结束标志
-
%s格式输出字符串,从字符串的首元素逐个字符输出,遇到'\0'结束
-
字符串常量用字符数组来储存
-
请描述:'a' 和 "a"的区别?
(六) 符号常量
-
用#define指令指定用一个符号代表一个常量
-
如:#define PI 3.1415926(注意末尾没有分号)
-
使用符号常量可以让常量在使用时含义更清楚,并且在需要改变程序中多处用到了同一个常量的时候,能够做到“一改全改”
(七) 地址常量
-
每一个常量、变量、数组的地址在程序运行期间是不能够改变的
二、变量与标识符命名
(一) 变量
-
系统根据变量的类型开辟对应的空间,其值可以被修改
-
变量名代表的是空间的内容,操作变量就是对空间内容的操作
-
变量必须先定义后使用
-
变量名的命名规则应符合标识符命名规则
-
C++中用const来定义常变量,该变量的值不能被改变
(二) 标识符
-
标识符命名规则:只能由字母、数字、下划线’_’组成,并且只能由字母和下划线开头
-
不能连续出现两个下划线,下划线不能紧跟大写字母开头
-
变量名用小写,类名用大4写
-
同一个作用域范围内定义的标识符不允许重名,不允许是关键字(系统定义有作用的)
(三)整型变量的操作
1、取值(读)、赋值(写)
-
局部变量不初始化,内容随机
int data = 0,num = 0;
printf("num = %d\n",num); // 读,取值
num = 100; // 写 赋值
printf("num = %d\n",num);
data = num; // num读 data写
2、输出
int num1 = 0;
// %d 有符号int数据输出
printf("num1 = %d\n", num1);
unsigned int num2 = 0;
// %u 无符号int数据输出
printf("num2 = %u\n", num2);
long num3 = 0;
// %ld 有符号long数据输出
printf("num3 = %ld\n", num3);
unsigned long num4 = 0;
// %lu 无符号long数据输出
printf("num4 = %lu\n", num4);
short num5 = 0;
// %hd 有符号short数据 输出
printf("num5 = %hd\n",num5);
unsigned short num6 = 0;
// %hu 无符号short数据 输出
printf("num6 = %hu\n",num6);
(四)auto 自动类型变量
(五)register 寄存器变量
-
register变量必须是一个单个的值,并且其长度应小于或等于整型的长度
-
局部变量和形参可以作为register变量,全局变量和静态变量不行
-
register变量可能不存放在内存中,不能用取址符运算符“&”来获取register变量的地址
register int num = 10;
// %p输出地址
printf("%p\n",&num); // 错误 不能对寄存器变量取地址
-
如果没显示标明 register,就类似int num。如果num被高频繁使用系统会自动将其放入寄存器,直接从寄存器里面读取数据,比从内存读取更快
-
主动加上register,就是告诉系统register修饰的变量将被频繁使用,对其分配地址时尽量将其分配在寄存器中,以提高访问速度
-
但是,这个修饰词只是告知cpu尽量将变量分配在寄存器中,不一定真的分配(可能优化处理)
三、基本数据类型
-
基本数据类型:用于定义变量,规定变量的数据类型,合理的利用空间
-
定义变量的基本格式:数据类型名 变量名(符合标识符规则)
-
注意长整型在不同平台占据的字节数
类型 | 类型标识符 | 在32位平台字节数 | 在64位平台字节数 |
---|---|---|---|
整型 | [signed] int | 4 | 4 |
无符号整型 | unsigned int | 4 | 4 |
短整型 | short int | 2 | 2 |
无符号短整型 | unsigned short int | 2 | 2 |
长整型 | long int | 4 | 8 |
无符号长整型 | unsigned long int | 4 | 8 |
字符型 | [signed] char | 1 | 1 |
无符号字符型 | unsigned char | 1 | 1 |
单精度型 | float | 4 | 4 |
双精度型 | double | 8 | 8 |
长双精度型 | long double | 8 | 8 |
(一)unsigned 和 signed(重要)
1、无符号数 unsigned
- 数据没有符号位,自身的所有二进制位都是数据位
- unsigned char表示范围:0000 0000 ~ 1111 1111
2、有符号数 signed 默认一般省略
- 二进制最高位为符号位,其他位为数据位
- 最高位为1表示负数,最高位为0表示正数
- signed char表示范围:1111 1111 ~ 1000 0000 ~ 0000 0000 ~ 0111 1111
(二)整型 int
-
整型数据以二进制方式储存,十进制数85的二进制形式1010101
-
被指定为有符号时,数值以补码形式存放,存储单元最高位用来表示数值符号
-
%u为无符号整型的输出格式
-
有符号与无符号相加,有符号转换为无符号
unsigned int a = 2147483647;
printf("%u\n", a); // 2147483647
a = -123;
printf("%d\n", a); // -123
printf("%u\n", a); // 当作无符号位输出,把符号位1当作数据位1,数值很大
(三) 字符型 char
-
占用一个字节
-
在C语言中,字符型数据在内存中以补码形式存放
-
取值范围:ASCII表
char ch = 'a';
printf("%c\n", ch);
printf("%d\n", ch); // %d的格式输出字符的ASCII码
(四) 单精度、(长)双精度型
float f = 3.14; // 定义了一个单精度浮点型float的变量f,并初始化赋值为3.14
printf("%f\n", f);
double PI = 3.1415926; // 3.141593
printf("%lf\n", PI); // %lf是双精度浮点型的格式占位符
long double ld = 123.456;
printf("%lf\n", ld);
四、数据类型的转换
- 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据定义的类型
(一)自动类型转换
- 占用内存字节数少(值域小)的类型,向占用内存字节数多(值域大)的类型转换,以保证精度不降低
- 数据类型的转换(从低到高):int(char、short) — unsigned int — long — double(float)
(二)案例
1、有符号和无符号的转换
- 有符号与无符号进行算术操作,有符号会转为无符号
int data1 = ‐20;
unsigned int data2 = 10;
// 有符号data1和无符号data2参加计算的时候,会先将data1转换成无符号(‐20的补码很大的正数)
// 很大的数 + 10 必然 >0
if(data1+data2 > 0)
{
printf(">0\n");
}
else if(data1+data2<0)
{
printf("<0\n");
}
- 运行结果:>0
2、int和double的转换
int data1 = 10;
printf("%d\n",sizeof(data1+3.14)); // 8字节
3、char和short转换
- 由于char、short自身字节数过小,很容易溢出。所以,只要char、short参加运算,都会将自身转换成int
char ch = 'a';
short data = 20;
printf("%d\n", sizeof(ch + ch)); // 4
printf("%d\n", sizeof(ch + data)); // 4
printf("%d\n", sizeof(data + data)); // 4
(三)强制类型转换
- 强制类型转换只是临时的转换,当前语句有效,在后面的语句中不会更改x的值
float f = (float)123.456; // 浮点型常量默认作为double类型数据处理
printf("%f\n", f);
int i = (int)f; // 浮点型赋值给整型,小数部分会被丢掉
printf("%d\n", i); // 有时候即使没有强制类型转换,编译器也会默认进行隐式类型转换
float x = 3.14f;
int j = 0;
//强制 类型转换 只是临时的转换 当前语句有效 在后面的语句中不会更改x的值
j = (int)x;
printf("j = %d,x = %f\n", j, x);
- 运行结果:j=3,x=3.140000
五、补充
(一)void 无类型 (重要)
- 不能用void 定义变量
void num; // 错误,系统不能确定给num开辟多大的空间
(二)volatile型变量(易失变量)
-
表示变量是易失的,易变的
-
强制访存操作,防止编译器去优化,告诉编译器每次必须去内存中取值,而不是从寄存器或者缓存
- 避免存放在寄存器里,不能得到及时的更新,误输出。
- 例如:烟雾传感器数据的保存,若数据10%存放在寄存器里,信息没有得到及时的更新,当数据达到临界值90%时,仍然读取10%,这样是很危险的
(三)字符输入输出函数
-
只能用于单个字符类型的输入和输出
char ch;
ch = getchar(); // getchar用从键盘获取一个字符
putchar(ch);
getchar(); // 吸收回车,由于getchar没有获取到字符就不会让程序继续往下执行,所以getchar()可以用来卡一下窗口
system("pause"); // 暂停窗口
- 案例:键盘输入 “abc” 只取 'a'和‘c’
char ch1,ch2;
printf("请输入abc:");
ch1 = getchar();
getchar(); // 丢弃一个字符
ch2 = getchar();
printf("ch1 = %c\n", ch1); // ac
printf("ch2 = %c\n", ch2);
(四) 整形数据溢出
-
当整型数据超出取值范围(计算机字长的界限),数据呈环形变化,也称叫数据出现溢出
-
short为例 二进制 十进制 0111 1111 1111 1111 + 1 = 1000 0000 0000 0000 1*2^15-1=32767 1111 1111 1111 1111 -1*2^15=-32768 -
数值范围为-32768~32767