目录
三、变量与常量
(一)定义变量的方法
int main () { int a = 150; float b = 15.5f; char ch = 'w'; return 0; }
如上所示,类型加自定义的名字,同时给其赋值,即为定义变量。
(二)变量的命名
1.变量命名原则
(1)只能由字母(包括大写和小写)、数字和下划线( _ )组成。
(2)不能以数字开头。
(3)长度不能超过 63 个字符。
(4)变量名中区分大小写的。
(5)变量名不能使用关键字。
2.经典的错误,标准的零分
int #ac //违背规则1,使用了#
int 2b //违背规则2,使用了数字开头
int char //违背规则5,使用了关键字
3.变量的分类
变量分为:局部变量和全局变量
区分方法:判断其位置,若在大括号外,则为全局变量;反之,则为局部变量
#define _CRT_SECURE_NO_WARNINGS int a = 10;//全局变量 int main() { int b = 20;//局部变量 return 0; } int c = 30;//全局变量
但是,如果若出现以下情况
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int a = 10; int main() { int a = 20; printf("%d", a); return 0; }
也就是说,局部变量和全局变量名字冲突,此时遵循:局部优先原则。
运行结果如下
小贴士:
尽量少使用局部变量
避免局部变量和全局变量冲突
4.变量的定义域与生命周期
(1)作用域
作用域( scope )是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效 可用 的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
①局部变量的作用域是局部变量所在的局部范围
#include <stdio.h> int main () { { int a = 1; } printf ("%d",a); return 0; }
上述代码,编译时报错。a出了这个大括号,就会被销毁。
②全局变量的作用域是整个工程
上述代码中,a的生命周期都是整个工程文件。
这里先说明一下extern
extern——声明同一个工程项目中的外部变量。
如上所示,在一个工程中创建了两个.c文件,在Test2.c中定义了一个变量,然后在Test.c中,使用extern这个关键词,来声明变量a,这个时候就能在Test.c这个文件中使用a这个变量了
③几个经典的错误,标准的零分
初级阶段,我们可能会由于概念不清,学识尚浅,导致了很多奇葩的错误。在这里我列举几个经典的错误
Ⅰ.如下所示,声明变量放在使用后面,这是个典型的因果倒置错误。代码首先经过编译以后才能运行,在编译的时候,我们的代码在test函数中的a还没有声明,就已经被使用。由此导致编译错误。
#include<stdio.h> void test() { printf("test:%d\n", a); } int a = 2022;//定义 int main() { printf("%d\n", a); test();//调用 return 0; }
Ⅱ.如下所示,一个printf不在任何一个函数体里面,在运行的过程中根本不会调用这个函数。
#include<stdio.h> int g_a = 2022;//定义 void test() { printf("test:%d\n", g_a); } int g_a = 2022;//定义 printf("%d", g_a);//Attention! int main() { printf("%d\n", g_a); test();//调用 return 0; }
④声明和定义的区别
上文中提及了很多名词,有时候说定义,有时候说声明,那这两有区别吗
肯定有。那区别在哪呢?
给出一段代码,来区分一下
int a;//声明
void test()
{
printf("test:%d\n", a);
}
int a = 2022;//定义
int main()
{
printf("%d\n", a);
test();//调用函数
return 0;
}
在这段代码中,第七行,int a = 2022;时,称作定义。无论这个定义靠前还是靠后,都被称作定义,但是可能会出现一个问题,变量a定义在使用的后面,这个时候编译器会直接报错。为解决这种情况,在第一行补上int a;但是没有赋值,此时,称作声明。
即:声明是为了防止编译器报错,先声明一下,我有这个变量存在,但具体值是什么,没定,在后面对其定义。当然,把定义放在第一行的话,此时的定义同样有声明的功能。
(2)生命周期
变量的生命周期,指的是变量创造到变量销毁之间的时间段
①局部变量的生命周期:进入作用域生命周期开始,出作用域生命周期结束
②全局变量的生命周期:整个程序的生命周期
5.常量
(1)常量的分类
常量分为以下四类:
① 字面常量
② const修饰的常变量
③ #define修饰的标识符常量
④ 枚举常量
(2)字面常量
#include<stdio.h>
int main()
{
//1 整数字面常量
//300 整数字面常量
//3.14 浮点数字面常量
//'a' 字符字面常量
//"abcjdksa" 字符串字面常量
return 0;
}
(3)const修饰的常变量
对于这个const修饰的常变量,很多人都比较疑惑,这名字起得比较奇怪,到底是什么意思呢,其实,“常变量”,常是修饰词,是由const进行修饰的,变量才是主语。
也就是说,const修饰的常变量,首先是一个变量,只不过由于const修饰,给其赋予了常属性(不可改变)。具有变量的一些性质
#include<stdio.h>
int main()
{
const int num =100 ;
num = 200;
return 0;
}
如上所示,在这里,我们已经用const修饰num了,如果我们还想要强迫改变num,对不起,编译器报错。
这也是个经典的错误,标准的零分,许多新手玩家都会在这里被坑。
(4)#define修饰的标识符常量
#define M 200
#include<stdio.h>
int main()
{
int a[M] = { 0 };
printf("%d", M);
M = 100;
return 0;
}
如上所示,使用define将M全部替换成200,注意,define这条指令是在预处理阶段进行的,将所有M全部替换成200。
我们知道,数组内元素的个数,是一个常数,调试没问题,这说明M本质上是一个常数。第二条语句中打印M,结果为200,这说明M被替换成200。第三条语句中想要强行修改M的值,抱歉,编译器报错。这再次说明,M是一个常数,具有常数性,不可被修改。
(5)枚举常量
这个概念,我们在数学中遇见过类似的,数学中有一种是枚举法,一般用于计算古典概型。
枚举在c语言中也是一样的,表示一一列举。跟数学的古典概型有区别的是,数学中的古典概型是有限个 ,或者是无限可列的但必须满足某种规律下(比如几何分布,巴斯卡分布等)。而我们c语言中的枚举仅仅代表前者,是有限个。比如血型,性别,三原色等等。
枚举的标识符是enum
#include<stdio.h>
enum Color {
RED,//0
//RED,GREEN,BLUE是枚举类型Color的可能取值,同时也是常量,所以叫枚举常量
GREEN,//1
BLUE//2
};
int main()
{
enum Color c = BLUE;
printf("%d\n", RED);
printf("%d\n", GREEN);
printf("%d\n", BLUE);
printf("%d", c);
}
如上代码所示,定义一个枚举类型,并执行语句,输出结果分别为0,1,2,2,这说明枚举常量中第一个被默认赋值为0,后面依次递增1。
关于枚举常量,后文还会有详细介绍,此处按下不表。
(6)经典的错误,标准的零分
①define 定义标识符常量后额外加了分号,有很多人在这块掉入了坑里,其实这块是不需要加分号的
②对const修饰词理解不够到位,误以为常变量是一个常量。我们知道,定义数组时的长度为一个常量,如果是变量则会报错,理论存在,实践开始。
如图所示,“表达式必须含有常变量”,证明完毕,M不可以使用在数组上,因为M本质是一个变量。
四、字符串与转义字符
(一)字符串
1.定义
“Hello World.\n”
形如这种,由双引号引起来的一串字符,被称为字符串字面值,或者简称字符串
2.字符串的结束标志
字符串的结束标志是一个叫“ \0 ”的转义字符。在计算字符串长度时候\0是结束标志,不算做字符串内容
3.字符串在数组中的存储
请思考,以下代码输出结果是??
#include<stdio.h>
int main()
{
char arr1[] = "hello";
char arr2[] = { 'h','e','l','l','o' };
printf("%s\n", arr1);
printf("%s\n", arr2);
return 0;
}
运行结果如下
为什么会第二个数组会出现这种情况呢?
字符串的结束标志是\0,第一个数组中,由于字符串常量默认最后一个是\0,所以可以正常打印。而对于第二个就比较糟糕了,因为他是一个字符一个字符输入进去的,这就导致了他的后续可能还有一堆其他乱七八糟的东西,也会一直打印出来,直到出现第一个\0。
这是监视窗口里的数据,再次验证了字符串在数组中的存储
4.字符串的长度
c语言中提供了一个库函数,叫做strlen,这个函数可以计算字符串的长度,统计的是\0之前的字符个数。strlen------string lenth ,属于string这个库中。
#include<stdio.h>
int main()
{
char arr1[] = "abc";
char arr2[] = { 'a','b','c' };
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
}
运行结果如下,
原因为,第一个数组末尾默认有一个\0,而第二个数组末尾并没有\0,又字符串的结束标志是\0,因此,编译器会一直往后计算,直至\0出现,故第二个数组的长度是一个随机值。
(二)转义字符
1.定义
先来看这两段代码
#include<stdio.h>
int main()
{
printf("abcdnf");
return 0;
}
#include<stdio.h>
int main()
{
printf("abcd\nf");
return 0;
}
输出结果分别为
此时,由于这个\n,导致了原本n的意思发生转变。
转义字符,就是将原来的字符的意思转变。
2.常见转义字符
转义字符 | 释义 |
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表示字符常量' |
\'' | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1~3个八进制的数字。如:130 X |
\xdd | dd表示两个十六进制数字。如:\x30 |
接下来详细讲解一下比较重要的转义字符
(1)转义字符 \?
这个转义字符,主要是避免三字母词使用的,那什么是三字母词呢。这里给出一段代码。
int main() { // ??) - 三字母词 - ] printf("(are you ok??)"); return 0; }
在一些编译器上会将??)这个转变成 ] 这个字符
为了避免这种情况,我们可以使用\?这个转义字符
(2)转义字符 \' \'' \\
这三个转义字符的作用是在想要打印出' " \这三种字符时候,用来表达这些字符
#include<stdio.h> int main() { //printf("%c\n", '''); printf("%c\n", '\''); //printf("%c\n", '"'); printf("%c\n", '\"'); return 0; }
如上述代码所示,只有加上转义字符,才能正常运行
(3)转义字符 \ddd \xdd
这两个转移字符跟其他的转义字符有些区别
\ddd这个转义字符中,他会将后面的1~3个八进制数字先转换成十进制数字,然后在ASCII表中找到对应的字符。这个字符就是最终的结果
同理
\xdd这个转义字符也是将后面的2个十六进制数先转换成十进制数,然后在ASCII表中找出对应的字符。这个字符就是最终的结果。
先附上ASCII表
#include<stdio.h> int main() { printf("%c\n", '\077');//077是8进制数字 printf("%c\n", '\x46'); return 0; }
下面给道练习题,请写出下列代码的输出结果
#include <stdio.h> int main() { printf("%d\n", strlen("abcdef")); printf("%d\n", strlen("c:\test\628\test.c")); return 0; }
3.比较:字符 '0',数字 0,字符 '\0'
'0'的ASCII值为48
0和'\0'本质一样,只是同一种东西的不同表现形式,0是数字形式,'\0'是字符形式
总结
本节主要讲述了,变量,常量,字符串以及转义字符等知识点的讲解。
请别忘了留下点赞关注收藏哟
另,本文所有代码均已上传至gitee,有需要的小伙伴们请自取呐
本站未完,欲知后事,请看下节