> 文档中心 > 【C语言百炼成神】功法一·常量与变量

【C语言百炼成神】功法一·常量与变量


💃🕺kiko小剧场


kiko:各位真的是好久不见,【百炼成神】专栏终于要回归了!

小明:真的是拖欠了好久哦🤯···我都不打算订阅了的说。

kiko:呜呜呜😭,我保证,以后一周至少两更!一周两更!

小明:行叭!那就赶紧开始叭~

🌟🌟往期必看🌟🌟

【C语言百炼成神】第一日·操作符

【C语言百炼成神】第二日·操作符

【C语言百炼成神】第三日·操作符

【C语言百炼成神】第四日·操作符

目录

💃🕺kiko小剧场

🍺知识点1:标识符与关键字

🍯1.1 标识符

🍯1.2 关键字

🍺知识点2:变量常量

🍯2.1 常量

🥝1.数值常量

🥝2.字符常量

🥝3.字符串常量

🥝附加1.字符串的结束标志问题

🥝4.符号常量

🍯2.2 变量 

🥝1.变量的定义

🥝2.变量的初始化和赋值

🥝3.全局变量与局部变量

🥝4.变量的作用域与生命周期

🍺知识点1:标识符与关键字


小明:咱们题目不是变量与常量吗?和这个有什么关系哦?

kiko:嘿嘿嘿,不懂了吧,考你个问题,我们把变量的名字叫作什么呢?

小明:变量名咯~

kiko:额···好像也对哦😅,不过这里就是想告诉你这个也可以认为是标识符。

🍯1.1 标识符


Q1:什么是标识符?

A1:在C语言中,常量、变量、函数名称都是标识符,标识符就好比是一个标签,它的名称是可以由用户亲自决定的,但是也不能随心所欲地命名,需要遵循一定规则。

Q2:命名标识符时需要注意什么?

A2:标识符的命名需要注意一下几点:

  • 标识符只能由【英文字母、数字、下划线】组合而成,并且第一个字符必须是英文字母或下划线,如下图所示。
int kiko6_name;  √(英文字母开头,正确)int _6kikoname;  √(下划线开头,正确)int 6_kikoname;  ×(数字开头,错误)
  • 不能使用C语言中保留的关键字;例如“int”就不能作为标识符,因为它在变量声明中充当了表示整型数据类型的作用,属于C语言的关键字。
float intt;    √(intt不是关键字,由英文字母组成,格式正确)float int;     ×(int是关键字,不能作为标识符)
  • C语言对大小写是敏感的,但程序中尽量不要出现仅靠大小写区分的标识符,容易混淆。
int o,O;//变量o与变量O容易混淆

kiko🎃:对于标识符的命名我希望大家可以做到直观清晰,让别人一看就能明白用途,我们可以采用英语单词或组合的方式创建标识符,便于记忆和理解;但是千万不要去用拼音去命名,同时也不要用数字进行命名,这样的名字会没有意义!!被我发现的话,拉出去打pp[○・`Д´・ ○]

创建一个“体重”标识符:float weight; √(使用体重的英文单词作为标识符)float tizhong;×(使用拼音)float weight_kiko;   √(用英语组合方式标识kiko的体重,直观清晰)float weight1;×(使用weight1标识,相比上面的kiko,完全没有意义)

🍯1.2 关键字


Q1:什么是关键字?

A1:关键字是C语言中的保留字,通常已有各自的用途,不能用作标识符。

🍺知识点2:变量与常量

kiko:在了解完这些基础后,我们先从常量开始介绍!

小明:刚刚不是说标识符和变量名有关么,咋先讲常量?

kiko:要你管奥,小子!

🍯2.1 常量


Q1:什么是常量?

A1:在程序中,有些数据是不会改变的,也是不能改变的,我们将这些不能改变的固定值称为常量;一些常见如下例所示。

printf("%d",15);     //这里的15——>数值常量printf("%c",'a');    //'a'——>字符常量printf("%s","kiko"); //"kiko"——>字符串常量

🥝1.数值常量

printf("%d",15);   //15——>整型常量printf("%d",-15);  //-15——>负数常量printf("%f",15.0); //15.0——>实型常量

字面理解就是表示数字的常量,通常表示的是数字。数字可以分为整型和实型,因此数值常量也可以分为整型常量和实型常量。

Q1:数值常量可以无限大下去吗?

A1:答案是否定的,数值常量在大到一定程度后就会出现错误。这是因为C语言中的量(常量、变量)在计算机中都要放在一个存储空间里,这个存储空间的大小是有限的,不能放无穷大的数据。


🥝2.字符常量

  printf("%c,%c,%c",'a','A','\n'); //依次输出'a','A',换行  printf("\069"); //输出八进制数(069)对应的ASCII字符——>9  printf("\x43"); //输出十六进制数(43)对应的ASCII字符——>C

一般情况:字符常量指的就是单引号' '里面的单个字符,如'a'、'x'等。

特殊情况:像'\n'、'\a'这样的字符常量就是转义字符。

Q1:什么是转义字符?

A1:转义字符通常以反斜杠(\)开头,后面跟一个字符或者一个八进制/十六进制数,此时表示的不是单引号里面的值,而是“转义”后的含义。

转义字符的应用案例:

//案例1:想单独打一个单引号、一个双引号、两个连续问号怎么办?int main(){    printf("%c\n", ''');    //error    printf("%c\n", '\'');   //'\''中\'表示单引号'    printf("%s\n", """);    //error    printf("%s\n", "\"");   //"\""中\"表示双引号"    return 0;}

//案例2:计算包含转义字符在内的字符串长度

kiko🎃:这是一道综合检验转义字符的题目,我们可以对其进行拆解作答,具体步骤如下。

kiko🎃:最终的答案为14,大家做对了嘛?


🥝3.字符串常量

例如"kikokingzz"就是字符串常量,用双引号括起来的形式表示,该字符串常量的值就是双引号里面的字符串。因此字符串可以定义为:在一对双引号里的字符序列,例如“、a\n”。

Q1:""与" "有区别吗?

A1:这两者是有明显的区别的。""称为空串,表示一个不包含任何字符的字符串;而" "则称为空格串,是一个包含空格字符的字符串。

Q2:请比较"a"与'a'的不同?

A2:我们可以从3个角度来进行讨论:

  • 书写形式不同:字符串常量使用双引号,字符常量使用单引号。
  • 二者操作不同:字符常量可以进行加减运算,而字符串常量则不能。
  • 存储空间不同:内存中,字符常量通常只占用1个字节,而字符串存储时会自动加一个结束标记'\0',所以'a'占1个字节,而"a"占2个字节。

kiko🎃:是不是存储空间这块没看懂?不要怕,我们马上就讲讲这个问题!


🥝附加1.字符串的结束标志问题

(1)字符串结束标志遇到 printf 函数时

在探讨之初,我们先看下面这一段程序:

#include int main(){    char arr1[]="abc";//数组    char arr2[]={'a','b','c'};    printf("%s\n",arr1);//%s打印字符串    printf("%s\n",arr2);    return 0 ;}

为什么在打印 arr2 时候会出现这么多烫呢?我们进一步调试一下,你就会发现答案~

kiko🎃:通过上面的调试我们发现,arr1中结尾自动加了一个结束标志'\0',printf打印字符串时会一直打到结束标志'\0',而在arr2中并没有添加结束标志'\0',printf会在打印完'c'后,一直往后打印,直到到发现'\0'才结束打印。

于是我们对此稍微修改一下原程序,在arr2后主动添加一个结束标志'\0',就可以实现正常打印啦:

    char arr2[]={'a','b','c','\0'};

(2)字符串结束标志遇到 strlen 函数时

Q1:什么是strlen函数?

A1:C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。

#include int main(){    char arr1[]="abc";    char arr2[]={'a','b','c'};    printf("%d\n",strlen(arr1));    printf("%d\n",strlen(arr2));    return 0 ;}

kiko🎃:strlen在计算字符串长度的时候 '\0' 是结束标志,不算作字符串内容。对于这里的 arr1,由于 arr1 是字符串,其最后自带一个隐藏的 '\0' ,strlen数到c就停止;对于 arr2,strlen会一直向后计数并寻找'\0',直到在随机值里找到'\0'才停止;所以这里的15是一个随机值,可能下次重新编译后,值就会改变。

当然我们也可以修改一下程序,使得arr2也可以实现1的操作:

改法1:char arr2[]={'a','b','c','\0'}; 改法2:char arr2[]={'a','b','c',0};//上面的'\0',也可用0代替,因为\0 的值是0


🥝4.符号常量

当某个常量比较复杂而且又被经常用到时,可以将该常量定义为符号常量,也就是用一个指定的名字代表一个常量,这被称为符号常量,即带名字的常量。

Q1:如何去定义符号常量呢?

A1:在C语言中,允许将程序中的常量定义为一个标识符,这个标识符称为符号常量,如下例中的标识符PI就是符号常量,其定义格式为:

#define  
  • 通常使用大写字母表示,变量名用小写字母标识。
  • 可以是数值常量,也可以是字符常量。
#define   PI     3.1415926  //用符号PI代替3.1415926在编译前,系统会自动把程序中的所有PI替换为3.1415926,在实际编译运行时系统只有3.1415926,而没有PI。

🍯2.2 变量 


🥝1.变量的定义

Q1:什么是变量?

A1:变量就像是一个存放数据的盒子,知道盒子的名字(变量名),也就可以找到盒子的位置(&变量名),以及盒子里的东西(变量的值),当然抽屉里的数据是可以改变的。因此我们说变量用于存储程序中可以改变的数据,变量的值是可以改变的。

kiko🎃:我们在这里简要讨论一下上面出现的专有名词,也就是变量的四大属性

  • 变量名:一个符合标识符定义规则的符号。
  • 变量类型:C语言中的数据类型或自定义的数据类型。
  • 变量位置:数据在内存中的存储空间地址。
  • 变量值:数据的存储空间中存放的值。

Q2:变量的定义与声明有什么区别?

A2:在理解区别之前,我们先来了解一下它们的定义。

(1)变量的声明:其实就是在程序运行前,向编译器描述变量的类型,但并不一定为变量分配存储空间。

(2)变量的定义:用于为变量分配存储空间,还可以为变量指定初始值。在程序中,变量有且仅有一个定义,但却可以声明多次。 

void main(){    int age;//既是声明又是定义,声明变量age是int类型,为变量age分配存储空间    double weight; //既是声明又是定义,声明变量weight是double类型,为其分配存储空间    extern int c;  //extern只作声明,不作定义,编译器不会给变量c分配内存空间}

🥝2.变量的初始化和赋值

Q1:请用一句话说清楚二者关系。

A1:由于变量的值在程序中可以改变,因此变量必然可以多次赋值,而我们将第1次的赋值称为变量的初始化。

int i = 10; //初始化变量iint j;      //定义变量jj = 10;     //为变量j赋值10

Q2:如何为多个变量赋值?

A2:这里其实涉及到了逗号运算符的细节,想要更好的了解这块内容,建议大家可以先补一补逗号运算符的内容,当然【百炼成神计划】肯定是想到这一点咯,可以看一下以下几期的内容:【C语言百炼成神】第一日·操作符

类型 变量名1=初始值,变量名2=初始值,变量名3=初始值···;案例1:请同时为a、b、c、d赋值4: int a=4,b=4,c=4,d=4;     // √(同时初始化多个变量) int a=b=c=d=4;    // ×(不满足规范) int a,b,c,d; a=b=c=d=4;  // √(先同时定义多个变量,后赋值)

🥝3.全局变量与局部变量

Q1:什么是局部变量与全局变量?

A1:全局变量定义在代码块  {  }  之外的变量;局部变量是定义在代码块  {  }  内部的变量。

#include int num2=20;     //全局变量-定义在代码块({})之外的变量int main(){    int num1=10; //局部变量-定义在代码块({})内部的变量}

Q2:全局变量与局部变量的优先级谁更高 

A2:当局部变量和全局变量的名字相同时,局部变量优先!

#include int a=20;int main(){    int a=10;    //局部变量与全局变量的名字建议必要相同,容易误会产生bug    //当局部变量和全局变量的名字相同时,局部变量优先!    printf("%d\n",a);} 


🥝4.变量的作用域与生命周期

Q1:什么是作用域?

A1:作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效的,而限定这个名字的可用性的代码范围就是这个名字的作用域,其中:

  • 局部变量的作用域是变量所在的局部范围。

  • 全局变量的作用域是整个工程。

Q2:什么是生命周期?

A2:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。

  • 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
  • 全局变量的生命周期是:整个程序的生命周期。

📝案例1:全局变量与调用函数

调用函数中如果没有重新定义局部变量,那么全局变量依旧可以起到作用。

#define _CRT_SECURE_NO_WARNINGS#include int global=2020; //全局变量的作用范围是整个工程void test(){    printf("test()--%d\n",global);//全局变量在函数内仍起作用}int main(){    test();    printf("%d\n",global);    return 0 ;}

📝案例2:extern与全局变量的作用域

全局变量的作用域是整个工程,因此只要是一个工程内声明的全局变量,就可以在其他项目中被使用。

//test2.c的内容:int kiko_age=22;//test.c的内容:#define _CRT_SECURE_NO_WARNINGS#include  int main(){    extern int kiko_age;//声明extern外部符号的    printf("%d\n", kiko_age);    return 0;}