【C语言从不挂科到高绩点】02-变量、数据类型、标识符、关键字
本套课程将会从0基础讲解C语言核心技术,适合人群:
-
大学中开设了C语言课程的同学
-
想要专升本或者考研的同学
-
想要考计算机等级证书的同学
-
想要从事C/C++/嵌入式开发的同学
分享不易,耗时耗力,麻烦给个不要钱的关注和赞吧
承接毕设指导,技术答疑,学习路上缺少导师的同学可以私信我
更多学习资料,公众号:墨轩学习网,B站:墨轩大楼
前文传送门:
二、变量和数据类型
计算机要处理的数据(数字,文字,图形,视频等等),都是以二进制的形式存储在内存中
我们将 8 个 bit(比特位)称为一个字节,并将字节作为最小的可操作单元。
2.1 变量
2.1.1 什么是变量
计算机用来存储可变数据的内存空间。
2.1.2 变量定义的步骤
- 声明变量(确定变量的类型和名字)
int age;
表示在内存中开辟了一个 int 类型的区域,给这块内存区域取了个名字叫 age
int 类型的变量,占 4 个字节,int age;可以理解成在内存中开辟了一个 4“平米”的空间
- 变量初始化(给变量赋值)
先通过变量名字找到变量对应的内存空间,然后往里面存储数据
age = 18;
表示,先根据 age 找到变量对应的空间,然后将 18 这个数据存储到 age 对应的内存空间中
- 上面这两步,可以合并
int age = 20;
表示:在内存中开辟了一块 int 大小的空间,命名为 age,向里面存储了 20 这个数据。
【演示案例】
/**定义变量的步骤:1. 声明变量(确定变量的类型以及变量名)2. 初始化变量(给变量赋初始值)**/#include<stdio.h>
int main(){//1. 声明变量(确定变量的类型以及变量名)int age;// 初始化变量(给变量赋初始值)age = 20;// 输出变量printf("年龄为:%d\n",age);return 0;
}
当变量赋初始化值之后,如果再给变量赋一个新值,那么这个新的值会将原来的值给替换掉
//1. 声明变量(确定变量的类型以及变量名)
int age;
// 初始化变量(给变量赋初始值)
age = 20;
age = 30;
printf("年龄为:%d\n",age);
如上面的代码,age 最开始赋值为 20,但是后面遇到了 age=30,那么 30 这个数据就会将 20 给替换掉,所以最后打印输出的时候,会输出 30
使用变量需要注意的问题:
- 变量使用之前必须声明并且初始化 ,如果不初始化,编译器会自动赋 0 值,但是往往会出现问题,所以建议手动赋 0 值
- 变量名不重复定义,不能定义两个名字相同的变量
【参考代码】
/**定义变量的步骤:1. 声明变量(确定变量的类型以及变量名)2. 初始化变量(给变量赋初始值)**/#include<stdio.h>
int main(){//1. 声明变量(确定变量的类型以及变量名)int age;// 初始化变量(给变量赋初始值)age = 20;// 注意:不能直接使用printf输出打印一个变量的值//printf(age);// 如果需要输出变量的值,需要用到 占位符// %d 占位符,表示此处是为一个整数占据位置// 程序运行起来之后,会将age的值填充到%d所占的位置上// printf("年龄为:%d,O(∩_∩)O哈哈~┭┮﹏┭┮\n",age);age = 30;printf("年龄为:%d\n",age);// 使用变量时需要注意的问题// 定义变量时,如果不初始化,运行起来之后,编译器会默认赋0值int num;printf("num:%d\n", num); //0// 一般建议:定义变量的时候如果不确定变量会存什么值,手动赋0值int num1 = 0;// 不同类型的变量,编译其给的0值不同double d1; // double是小数类型,稍后讲//%lf 是double类型的占位符printf("d1:%lf\n",d1);// 0.000000//变量在使用之前,必须声明//printf("num2:%d",num2); // 错误,num2 没有定义// 变量名不能重复定义,两个变量的名字不能相同int age = 0;printf("%d\n",age);return 0;
}
2.2 常量
常量一旦定义的数据不能发生改变
常量定义两种方式:
- 采用#define 定义宏的方式
- 采用 const 关键字定义
/**常量的定义**/#include <stdio.h>// 方式一: 以宏的方式定义常量 (宏先用着,后面详细讲)#define MAX 20 // 注意,此处后面不加分号
// 定义了一个常量MAX 里面存20int main(){int a;a = MAX; // 每次使用MAX的时候,编译代码之前就会用20替换MAXprintf("a=%d\n",a);// 20//MAX = 30; // 尝试修改MAX的值// 编译的时候,就会出错,常量的值一旦定义之后,就不能改变了// 方式二:使用const关键字定义常量const int b = 100; // 在变量定义之前加const,那么意味着这个b就是常量printf("b=%d\n", b);//b = 250; // 报错:assignment of read-only variable ‘b’// 说明b是只读的printf("b=%d\n",b );}
如果尝试去修改常量,可能就会出现如下两种错误:
2.3 数据类型
2.3.1 数据类型作用
定义变量的格式
数据类型 变量名 = 值;
数据是存放在内存中的,变量名是给这块内存取的名字,声明变量的时候,需要给变量在内存中开辟一块空间。但是问题是:计算机是怎么知道要开辟多大空间的?
此时就需要用到数据类型,不同的数据类型开辟的空间是不一样的,能存储的数据也不一样
int age;
age 是 int 类型的,计算机看到了 int 就知道要开辟 4 个字节大小的空间
数据类型实际上就是一种告诉计算机应该为变量开辟多大空间的标志。
2.3.2 基本数据类型
整数类型:C 语言中用来表示整数的类型
short
int
long
long long
浮点型:用来表示小数的类型
float :单精度小数
double :双精度小数
字符类型:用来表示符号的(a-z,A-Z,+ - * / 等等)
char
注意:C 语言中的字符类型占一个字节
2.3.3 各种数据类型的长度
数据类型的长度:是指数据类型要占用多少个字节,占用的字节越多,能存储的数据越多,对数据来说,能表示的值就越大
获取数据类型或者变量的字节数据使用的函数:sizeof(数据类型)或者 sizeof(变量名)。
/**各种数据类型的长度(占用的字节数)**/#include <stdio.h>int main(){int a = 2000000;// sizeof(变量名) 表示:求出变量所占用的字节数(占用多少内存)// sizeof(数据类型) 表示:求出的是数据类型对应的字节数// sizeof() 最终的结果是long类型的// %ld 是long类型的占位符printf("变量a的长度为:%ld\n",sizeof(a)); // 4printf("int类型的长度为:%ld\n",sizeof(int)); //4printf("int类型的长度为:%ld\n",sizeof(short)); //2printf("int类型的长度为:%ld\n",sizeof(long)); //8printf("int类型的长度为:%ld\n",sizeof(long long)); //8printf("int类型的长度为:%ld\n",sizeof(float)); //4printf("int类型的长度为:%ld\n",sizeof(double)); //8printf("int类型的长度为:%ld\n",sizeof(char)); //1// 变量所占用的长度(字节数)和它对应的数据类型的长度一致return 0;
}
需要注意的问题:
- sizeof(变量名) 表示:求出变量所占用的字节数(占用多少内存)
- sizeof(数据类型) 表示:求出的是数据类型对应的字节数
- sizeof() 最终的结果是long类型的 。%ld 是long类型的占位符
需要大家重点记忆的表格
数据类型 | int | short | long | long long | float | double | char |
长度 | 4 | 2 | 8 或者 4 | 8 | 4 | 8 | 1 |
需要注意:对于 long 类型而言,在 Linux 系统中占 8 个字节但是在 windows 系统中占 4 个字节。
2.3.4 整数数据类型
打印格式 | 含义 |
%d | 输出一个有符号的 10 进制的 int 类型 |
%o (字母 o) | 输出一个 8 进制的 int 类型 |
%x | 输出 16 进制的 int 类型,字母以小写输出 |
%X | 输出 16 进制的 int 类型,字母以大写输出 |
%u | 输出 10 进制的无符号位 int 类型整数 |
参考代码
/**整数类型
**/#include <stdio.h>int main(){int a = 123;// 定义了变量a,以10进制的方式赋值为123// 在C语言中,0开始的整数表示为8进制int b = 0567; // 定义了一个变量b,以8进制的方式赋值为567// 0x 或者 0X 开始的表示为16进制数int c = 0xabc; // 定义了变量c,以16进制的方式赋值为abcprintf("十进制输出:a=%d\n",a);// %o是八进制占位符,所以输出的时候,会将10进制a转换成八进制printf("八进制输出:a=%o\n",a);printf("十六进制输出:a=%x\n",a);printf("十六进制输出:a=%X\n",a);printf("---------------------\n");printf("8进制:b=%o\n",b );printf("10进制:b=%d\n",b);printf("16进制:b=%X\n",b);printf("---------------------\n");printf("8进制:c=%o\n",c );printf("10进制:c=%d\n",c);printf("16进制:c=%X\n",c);return 0;
}
有符号位和无符号位的区别:
- 有符号数是最高位为符号位(二进制),最高位数字如果是 0 代表正数,1 代表负数
- 无符号数是最高位不是符号位(二进制),而是数的一部分,无符号数,不能是负数
当写一个程序要处理一个不可能出现负数的情况,一般使用无符号数,这样可以增大值的表示范围。
2.3.5 浮点类型
C 语言中小数两种表示形式
1. 十进制表示法: 0.75 1.23 3.14
2. 指数表示法: 2.1E3 3.7E-3 0.5E7
C 语言中小数的指数表示方式
aEn 或者 aen
- a 表示尾数部分,是一个 10 进制数(大于 0,小于 10)
- n 表示指数部分,是一个 10 进制数
- e 或者 E 固定的字符,用于分割尾数部分和指数部分
- 整个表达式等价于:a*10^n ,a 乘以 10 的 n 次方
2.1E5 = 2.1 * 10^5
3.7E-3 = 3.7* 10^-3
C 语言中的小数类型有两种
1. float 类型(单精度小数) : 占4个字节
2. double类型(双精度小数): 占8个字节
小数的输出占位符
%f 以10进制的方式输出float类型
%lf 以10进制的方式输出double类型
%e 以指数形式输出float类型,输出的结果e是小写的
%E 以指数形式输出float类型,输出的结果E是大写的
%le 以指数形式输出double类型,输出结果e是小写的
%lE 以指数形式输出double类型,输出结果E是大写的
【案例代码】
/**
C语言中的小数
**/#include <stdio.h>int main(){float a = 0.302;printf("a=%E\n", a); // aEn 3.020000e-01float b = 128.101;printf("b=%E\n",b );//1.281010E2// 很多情况下,小数并不能准确的表示,会有些偏差// 128.101 不是准确的128.101 而是一个接近于这个数据的128.100998printf("b=%f\n",b);//128.100998// 无论是指数形式还是十进制形式输出小数时,默认情况都是保留6位小数// 如果不足6位的会用0补齐// 如果需要保留指定位数的小数// 可以使用%.nf ,表示,保留n位小数printf("b=%.1f\n",b);printf("b=%.3f\n",b);// 可以将一个整数赋值给小数// 会在整数后面添加小数点,后面补6个0double c = 123;printf("c=%lf\n",c); //123.000000// 默认情况下,小数点后面保留6位小数,// 超过六位,会按照四舍五入的方式舍弃掉超出的部分float e = 0.7683e-4;//0.00007683printf("e=%f\n",e); //0.000077// float e = 0.7633e-4;// printf("e=%f\n",e); //0.000077// 编译器默认的小数类型是double类型,如果要确定这个数float类型的//可以在小数后面加上f,标志这个是float类型float n = 1.24f;printf("n=%f\n",n);return 0;
}
需要注意的点:
- %f 和%lf 默认保留 6 位小数,不足六位以 0 补齐,超过 6 位,按照四舍五入的方式舍弃。如果需要展示 n 位小数,可以使用%.nf 或者%.nlf.
- 将一个整数赋值给小数类型时,整数会自动转换成小数
- 以指数形式输出小数时,输出的结果为科学计数法,也就是说尾数部分取值范围是大于 0,小于 10
- 很多小数在内存中不能精确的存储,所以有的小数取出来会存在一些偏差。比如:128.101 在内存中存储的不是准确的 128.101 而是一个接近这个数据值128.100998
小数和整数之间相互赋值
C 语言中,小数和整数是可以相互赋值的
- 将一个整数赋值给小数,会在整数后面直接加小数点和 0
- 将一个小数赋值给整数,会将小数部分直接丢弃掉(注意:不是四舍五入)
#include <stdio.h>int main(){// 将小数赋值给整数变量时,会直接丢弃小数部分(不是四舍五入)int w = 19.427;printf("w=%d\n", w); //19int y = 92.78;printf("y=%d\n",y);//92int x = -87.89;printf("x=%d\n", x);// -87return 0;
}
2.3.6 字符数据类型
C语言中用来表示字符的数据类型是 char 类型,长度为 1.只能容纳 ASCII 码表中的字符,也就是英文字符。如果要处理汉语,日语,韩语等等字符,单纯的用 char 就很难。这个时候就要用到字符串(字符数组)
可以终端,输入以下指令查看 ASCII 码
man 7 ascii
ASCII 码表的内容:
ASCII值 | 控制字符 | ASCII值 | 字符 | ASCII值 | 字符 | ASCII值 | 字符 |
0 | NUT | 32 | (space) | 64 | @ | 96 | 、 |
1 | SOH | 33 | ! | 65 | A | 97 | a |
2 | STX | 34 | " | 66 | B | 98 | b |
3 | ETX | 35 | # | 67 | C | 99 | c |
4 | EOT | 36 | $ | 68 | D | 100 | d |
5 | ENQ | 37 | % | 69 | E | 101 | e |
6 | ACK | 38 | & | 70 | F | 102 | f |
7 | BEL | 39 | , | 71 | G | 103 | g |
8 | BS | 40 | ( | 72 | H | 104 | h |
9 | HT | 41 | ) | 73 | I | 105 | i |
10 | LF | 42 | * | 74 | J | 106 | j |
11 | VT | 43 | + | 75 | K | 107 | k |
12 | FF | 44 | , | 76 | L | 108 | l |
13 | CR | 45 | - | 77 | M | 109 | m |
14 | SO | 46 | . | 78 | N | 110 | n |
15 | SI | 47 | / | 79 | O | 111 | o |
16 | DLE | 48 | 0 | 80 | P | 112 | p |
17 | DCI | 49 | 1 | 81 | Q | 113 | q |
18 | DC2 | 50 | 2 | 82 | R | 114 | r |
19 | DC3 | 51 | 3 | 83 | S | 115 | s |
20 | DC4 | 52 | 4 | 84 | T | 116 | t |
21 | NAK | 53 | 5 | 85 | U | 117 | u |
22 | SYN | 54 | 6 | 86 | V | 118 | v |
23 | TB | 55 | 7 | 87 | W | 119 | w |
24 | CAN | 56 | 8 | 88 | X | 120 | x |
25 | EM | 57 | 9 | 89 | Y | 121 | y |
26 | SUB | 58 | : | 90 | Z | 122 | z |
27 | ESC | 59 | ; | 91 | [ | 123 | { |
28 | FS | 60 | < | 92 | / | 124 | | |
29 | GS | 61 | = | 93 | ] | 125 | } |
30 | RS | 62 | > | 94 | ^ | 126 | ` |
31 | US | 63 | ? | 95 | _ | 127 | DEL |
ASCII 码大致分为了两个部分:
- ASCII 非打印字符
ASCII 码表中的编号 0-31 分配给了控制字符,用来控制打印机等外围设备
- ASCII 打印字符
编号为 32-126 分配给了能在键盘上找到的字符,space 表示空格,127 给了 DEL 命令
其中,字符 0 对应的编号是 48,字符 a 对应的编号是 97,字符 A 对应的编号是 65(记一下).
/**
字符数据类型**/#include <stdio.h>int main(){// 定义字符类型的变量char a = 't'; // 字符需要用单引号包裹。printf("char 类型的长度:%ld\n",sizeof(char));printf("char 变量的长度:%ld\n",sizeof(a));// char的长度为1,一个字节,里面只能放一个字符//char b = 'ab'; 错误// char类型的输出占位符 %cprintf("a=%c\n",a);// Linux系统中,中文默认占3个字节,char类型只有一个字节// 所以,char中不能存中文// char c = '帅';// printf("c=%c",c);}
需要注意的问题:
- 字符的值需要用单引号包裹。
- char的长度为1,一个字节,里面只能放一个字符
- char类型的输出占位符 %c
- Linux系统中,中文默认占3个字节,char类型只有一个字节,所以,char中不能存中文
字符数据类型在内存中的存储
字符在内存中不是存的字符实体,而是存储字符在 ASCII 码字符集中的编号,也可称为编码值,对于 char 来说,实际存储的就是 ASCII 码值。
char b = '1';// 字符1// 由于字符在内存中存储的是ASCII码值,这个是整数// 所以ASCII编码值,按照int类型的方式输出printf("b=%c ,%d\n",b,b); //49char e = '$';printf("e=%c, %d\n", e,e ); //36char r = ' ';printf("r=%c, %d\n", r,r ); // 32
实际上 ASCII 码表将英文字符和整数关联起来,我们可以将字符赋值给 int 类型的变量,同时也可以将整数赋值给字符类型,但是需要注意范围:
// 对于单个字节而言,有符号位,取值范围是:-128到127
// 当超过127的时候,数据会溢出,变成负数,最多也不能超过255,否则就会出错
char n = 255; // 将整数赋值给了char类型
printf("n=%c, %d\n", n,n );//char m = -129; // 数据溢出,编译出错
//printf("m=%c, %d\n",m,m );//char n = 258; // 超过了255 编译会出错// 无符号位,因为没有负数,所以一整个字节都是用来表示整数
// 取值范围:0-255
unsigned char j = 255;
printf("j=%c, %d\n", j,j );char u = 128;
printf("u=%c,%d\n",u,u );
// 虽然char表示的数值范围是-128到127之间,但是只要不是0-127(ASCII码值的范围)之间的数值
// 转换成字符之后,都会呈现出乱码
需要注意的问题:任意一个字符,都可以赋值给一个整数变量,但是整数赋值给字符变量时,需要注意范围。有符号位 char 字符,能放-128 到 127 之间的数字。无符号位的 能放 0-255 之间的数字。
数据溢出:
2.3.7 C 语言中的转义字符
转义字符 | 含义 | ASCII码值(十进制) |
\a | 警报 | 007 |
\b | 退格(BS) ,将当前位置移到前一列 | 008 |
\f | 换页(FF),将当前位置移到下页开头 | 012 |
\n | 换行(LF) ,将当前位置移到下一行开头 | 010 |
\r | 回退(CR) ,将当前位置移到本行开头 | 013 |
\t | 水平制表(HT) (跳到下一个TAB位置) | 009 |
\v | 垂直制表(VT) | 011 |
\\ | 代表一个反斜线字符"\" | 092 |
\' | 代表一个单引号(撇号)字符 | 039 |
\" | 代表一个双引号字符 | 034 |
\? | 代表一个问号 | 063 |
\0 | 数字0 | 000 |
\ddd | 8进制转义字符,d范围0~7 | 3位8进制 |
\xhh | 16进制转义字符,h范围0~9,a~f,A~F | 3位16进制 |
参考案例
#include <stdio.h>int main(){// \r 回退,让\r所在的位置出现在当前行的开头printf("不是一个人的王者");printf("\r而是团队的荣耀\n");printf("\r天王盖地虎\n");// \t 制表符,相当于键盘的Tab键 // 制表符不是单纯的空格printf("德玛\t西亚!人在\t塔在!\n");// \ddd 比如:\123 表示将十进制的123 转换成8进制的0123printf("%c %o %d \n",'\123','\123','\123');// 所谓的转义字符,实际是将单引号中的内容,转换成一个字符// '\x23' 将10进制的数字转义成16进制的0x23printf("%c %X %d \n",'\x23','\x23','\x23');return 0;
}
2.3.8 定义变量的多种形式
#include <stdio.h>int main(){int age = 20;// C语言中支持连续定义多个数据类型相同的变量int a,b,c; // 表示连续定义了3个int类型的变量// 定义多个变量的时候,同时赋值float m=1.23,n=3.14;char p,q = 'w';printf("%c %c\n",p,q);return 0;
}
三、标识符和关键字
3.1 标识符
在定义变量的时候,会给变量取名,定义函数的时候会给函数取名。像这种函数名,变量名,结构体名等等,这些名字统称为标识符。
标识符的命名规则,必须遵守的规则(法律)
- 标识符只能由字母(A-Z a-z ),数字 (0-9),下划线 _ , $组成
- 标识符不能以数字开始
- 标识符不能使用关键字
- 标识符是区分大小写的,book 和 Book 是两个不同的标识符。
/**C 语言中的标识符
**/
#include <stdio.h>int main(){//标识符名称不允许以数字开始//int 2b = 9; //错误int sb = 7;// 标识符中除了_ 和 $ 以外不能包含其他特殊字符int a_b$ = 8;//int a#b = 9; // 不能包含特殊符号// int const = 5; // const 是C语言中的关键字// 变量名不能重复定义// 标识符区分大小写,下面两个变量是不同的变量int book_num = 89;int Book_num = 78;return 0;
}
标识符的命名规范(道德)
见名知意:看见标识符的名字,就知道存的是什么数据,或者是干什么的。
比如:变量名:age,就能推断出它是用来保存年龄的。
函数名:get_age() 就知道这个函数就是用来获取年龄的函数
3.2 关键字
关键字是由 C语言已经规定了具有特殊含义的字符串,通常也称为保留字。比如:int,const。我们在定义标识符的时候,不能使用关键字。
关键字就是具有特殊含义的标识符,他们已经被系统使用了,我们不能再使用了。
标准 C 语言一共规定了 32 个关键字(在给标识符取名时,要避开这些关键字)
- 数据类型关键字(12 个)
char 、 double、float、short、int、long、signed、unsigned、struct、union、void、enum
- 控制语句相关关键字(12 个)
循环语句:for、do、while、break、continue
条件语句:if 、else、goto
开关语句:switch、case、default
返回语句: return
- 存储类型关键字(4 个)
auto、extern、register、static
- 其他关键字(4 个)
const、sizeof、typedef、volatile
我们在使用标识符时,应该避开这 32 个关键字