c基础教程第十讲(C探索之旅)(1)

内容简介

1、第一部分第四课:内存,变量和引用

2、第一部分第五课预告:简易计算器

内存,变量和引用

上一课《【C 探索之旅】第一部分第三课:第一个C 程序》http://blog.csdn.net/frogoscar/article/details/46700743 中,我们已经学习了如何创建,编译,运行我们的第一个C 程序。我们也解释了这个程序每一行的意义。

我们不但在IDE(Integrated Development Environment,集成开发环境。例如Visual Studio,Codeblocks,xCode等)中创建程序,也学习了如何在终端命令行中创建。

不过到目前为止,我们写的程序还非常简单,只能在屏幕上显示消息,还不能和用户进行交互。我们慢慢来弥补这一缺憾。

在此之前,我们首先来学习一个计算机科学的基本概念,就是:变量。

电脑的内存的原理就有点像一个有着很多抽屉的大橱柜。

对于一个计算器来说,我么通常一次只能储存一个数值。但是我们的电脑可比普通的计算器厉害多了。不然也不会那么贵了,对吧?说的就是你,苹果电脑。

聪明如你应该料想到了:在C 程序中,我们可以同时储存很多变量。因此,就需要区分这些变量,以便之后调用时可以分得清谁是谁。因此,在C 程序中,每个变量拥有一个名字。这个名字就有点像上图中的抽屉外面贴的标签,使我们能够找到所要的抽屉。

我们的电脑还可以使我们储存不同的数值,比如我们想储存数字,字母,单词,句子,图片,声音,等等。这就涉及到变量的类型了。

你可以想象变量的类型就好比抽屉的不同样式,在生活中,我们放葡萄酒和书籍的抽屉是不一样的,不是吗?

变量名

对于人来说,名字很重要,名字起得好,有很多益处。名字起得不好,会很搞笑。

c基础教程第十讲(C探索之旅)(2)

变量也有名字,而给C 中的变量起名字有如下规则:

  1. 只能包含字母,数字和下划线(_)

  2. 第一个字符必须是字母或下划线

  3. 不能和C 的关键字重复,比如不能是int,char,if,while等。

例如:

name,studentNum,year2015,_computerPrice 等都是规范的命名。

而:

animal,@gmail,*1991,等都是通不过的命名。

除此之外,C 对于大小写敏感。也就是说,大写字母和小写字母在C 看来是不同的。有的编程语言不区分大小写。所以,在C 中,givenName,GIVENname,GiVenName是不同的变量名。

另外,希望大家养成良好的命名习惯,使自己的变量做到见名知意,这样程序就可以自注释了。比如,我们提倡这样的变量名:myName,computerPrice。而不推荐类似 name1,variable3,hehe2,之类不知所云的名字。

对于程序的编译器来说,这样并没有什么用,因为它才不管你名字起得是不是见名知意。但是,对于你自己和以后要阅读你的程序人来说,一个好的变量名会发挥很大的作用,不然过了一段时间再看自己的代码,可能都忘了这个变量是用来干嘛的。

小编自己有个变量命名习惯,此习惯不少程序员也遵守:

  1. 变量名由小写字母开头

  2. 如果变量名由几个单词组成,那么紧挨着写

  3. 除了第一个单词,其他单词的第一个字母大写

例如:

bestRestaurantName,secondBugReport,等等。

这样的命名法也称为《小驼峰式命名法(lower camel case)‍》。

变量类型

之前说了,变量除了有名字,还有类型。就好比“小明”这个名字,不知道是人呢还是一只宠物。

C 的变量类型如下图所示:

c基础教程第十讲(C探索之旅)(3)

有点多是吗?初学时不用一下子都记住,我们慢慢来学习。一开始只要知道几种常用的变量类型就可以了。如下:

常用类型可以存储的数值
booltrue(真)或false(假)
char一个字符
int整数
unsigned int无符号整数(正整数或0)
double带小数点的数(其实double是双精度浮点数)
string字符串(0到多个字符)

一般,我们在IDE中输入以上这些变量类型时,IDE会用颜色来高亮显示。

这些类型可储存的数值有大小范围,也就是上下限。比如有的很大的整数,int类型就不能储存。这些上下限取决于你的电脑,操作系统和编译器。

当我们使用变量时,就需要考虑用哪种变量类型了。例如你要储存一个学校的学生数目,那么int和unsigned int会适合。要储存一个人的身高,那么用double会适合。要储存你自己的名字,那么string会适合。

那么bool这种变量类型是什么意思呢?

bool其实是boolean(布尔类型)的意思,它只能储存两种值:true(真)或false(假)。

我们可以用bool类型的变量来储存例如: 用户名是否正确,是不是程序员,有没有女朋友,之类。

变量声明

变量的英语是variable,是《可变的,变化不定的》,所以说,变量和女人的心有点像,不是吗?开个小玩笑。

因此,变量储存的数值是可以改变的。

好了,铺垫也够多了,该来正式请求电脑出借它的“抽屉”了(前面我们用抽屉比喻一块内存空间)。用术语来说,就是变量声明。

注意:我们暂时用《声明》这个词,其实要澄清一下:

==========================

对 变量而言,声明与定义的关系稍微复杂一些。在声明部分出现的变量有两种情况:一种是需要在内存中建立存储空间的(如int a;);另一种是不需要建立存储空间的(如extern int a; 以后会讲到extern关键字)。前者称为定义型声明(defining declaration),或简称为定义(definition)。后者称为引用型声明(referenceing declaration)。

广 义地说,声明包括定义,但并非所有的声明都是定义。对 int a; 而言,它是定义性声明,既可说是声明,又可说是定义。而对 extern int a; 而言,它是声明而不是定义。一般为了叙述方便,把建立存储空间的声明称为定义,而把不需要建立存储空间的声明称为声明。

在这一课中所有用到《声明》的地方,其实用的是《定义型声明》。以后的课会讲解《引用型声明》。

==========================

我们需要向电脑提供变量的类型,名字和它储存的值。这里的值会成为变量的初始值。

为了做到这一点,我们只需按照以下格式:

类型 名字 (值);

以上的格式是C 中初始化一个变量的方式。

我们也可以用另一种从C语言继承过来的格式:

类型 名字 = 值;

这两种格式的效果是一样的。我们推荐使用第一种格式,以后的课程中会讲述为什么选第一种格式更好。

可不要忘了句末的分号(;),这个错误即使是有经验的程序员也会犯。当然这个错误也不难发现,只不过它会让你的编译器不安分而已。

我们就来声明(定义型声明)一个变量,这个变量叫做userAge,用于储存《用户年龄》:

#include <iostream>

using namespace std;

int main()

{

int userAge(16);

return 0;

}

上面程序的第6行发生了什么呢?

答:电脑得知我们要向它的内存借一个“抽屉”,这个抽屉有以下特性:

  1. 可以储存整数

  2. 抽屉外面贴了一个标签,名叫 userAge

  3. 抽屉里储存的值是16

因此,一旦程序运行完了第6行代码,你就成为电脑内存中那个抽屉的主人了,如下图:

c基础教程第十讲(C探索之旅)(4)

因为之后我们会继续向电脑借很多“抽屉”,所以我们需要把图画得简单些。如下:

c基础教程第十讲(C探索之旅)(5)

我们来解释一下上图的意思:

  1. 大大的蓝色矩形代表的是电脑的内存,目前,内存几乎是空的。

  2. 黄色的小正方形代表电脑出借给我们的内存的一块空间。也就是我们之前比喻的一个抽屉。它里面储存的值是16,而它的标签是userAge。

既然我们画了如此好(chou)看(lou)的图,那岂能只声明一个变量。一不做二不休:

#include <iostream>

using namespace std;

int main()

{

int userAge(16);

int money(432); //钱数

double pi(3.14159);

bool isHoliday(true); //是不是假期

char letter('a');

return 0;

}

上面的程序中,我们在userAge这个变量之外,又声明了好几个新的变量。

有两点需要注意:

  1. bool类型的变量只能储存true或false中的一个值,不是true(真),就是false(假),除此之外不能储存其他值。

  2. char变量的值需要用单引号括起来,不要写成 char letter(c); 而是 char letter('c');

插一句题外话:写程序时要勤写注释,哪怕看似比较简单的地方,因为以后别人看你的程序,或者你自己回看自己的程序,假如没有注释,那可能会增加不少难度。

对于上面这个程序,我们也可以画一个图,只要在之前的图上增加新的变量即可。

c基础教程第十讲(C探索之旅)(6)

可以看到,我们多声明了几个变量,内存里面开始变得丰富多彩起来了。马上要圣诞了,人多一些总是热闹。

上面的程序,我们如果编译,运行,可以看到它什么也没有输出。那是当然的,因为我们只是声明了一些变量,还没使用它们呢。

我希望你没有太失望,虽然这个程序没有显示什么,但其实在背后电脑是进行了很多操作的。只不过这些操作对用户隐藏起来了,我们也不太感兴趣而已。不过我们还是总结一下上面的变量声明究竟做了什么:

  1. 你的程序向操作系统(简称OS,是Operating System的缩写。例如Windows,Mac OS X,Linux等都是常见的操作系统)借一些内存来使用

  2. 操作系统查看内存是否有空余的空间,如果有则分配几个“抽屉”(代表内存空间)给你的程序

  3. 你的程序逐一将那些值存放进对应的抽屉。例如在贴有userAge标签的抽屉里,存放进16;在贴有money标签的抽屉里存放进432;等等

  4. 运行到最后一行(return 0;)时,你的程序把所有抽屉清空,并且还给操作系统

字符串的情况

前面说了,字符串这种变量类型的情况有点特殊。为了使用字符串变量,我们首先需要在程序中多加一行:

#include <string>

表示引入string这个C 的标准库,这样我们才能使用其中的函数等。我们可以写个程序:

#include <iostream>

#include <string>

using namespace std;

int main()

{

string userName("Steve Jobs");

return 0;

}

可以看到,我们声明了一个字符串变量,它的名字是userName,里面存放的值是Steve Jobs(苹果的前CEO)。

可以看到,给string型变量赋值,用的是双引号",而之前给char型变量赋值时用的是单引号'。其实呢,字符串(string)就是由一串字符(char)组成的。

偷懒的小技巧

在继续下面的内容之前,我们介绍一种“偷懒”的小技巧,很多程序员都会用:

如果你有多个同一类型的变量要声明,那么可以将它们放在同一行里,彼此用逗号隔开。如下:

int a(2), b(4), c(6); //我们声明了三个整型变量a, b, c,分别存放了2, 4, 6三个值

string userNameApple("Steve Jobs"), userNameMicrosoft("Bill Gates"); //我们声明了两个字符串变量userNameApple和userNameMicrosoft,分别存放Steve Jobs(史蒂夫乔布斯)和Bill Gates(比尔盖茨)。

这样我们就不用每次都写一遍变量类型名了,上例中是int和string。

声明但不初始化

上面我们学习了如何声明一个变量(其实是定义型声明),其实声明一个变量时你的程序陆续做了两件事:

  1. 首先,程序向操作系统请求拨给一块内存空间,称为“变量分配”。

  2. 然后,在这块内存空间上存入初始值,称为“变量初始化”。

但是,有的时候我们在声明变量时还没有想好要赋什么值。所以,我们也可以声明变量,但不初始化。

怎么做呢?很简单,只需要写变量类型和变量名,就可以了。如下:

类型 名字;

是不是很简单呢?我们来看例子程序:

#include <iostream>

#include <string>

using namespace std;

int main()

{

string qqName; // QQ用户名

string qqNumber; // QQ号

bool isVIP; // 是不是QQ的VIP会员

return 0;

}

注意:有一个常见的错误是:

在变量名之后加空的括号,例如 string qqNumber();

这是不正确的,不要加括号,只需要类型和名字。

我们也用图解来演示上面的程序:

c基础教程第十讲(C探索之旅)(7)

可以看到,在声明变量后,变量中的值是一个任意值。

但是通常我们最好在声明时给变量赋初值,特别是指针的情况,以后我们会学习。而且有的变量类型还必须在声明时就初始化。

显示变量的值

在上一课中,我们已经学习了如何在屏幕上显示文本,希望你没有忘记大明湖畔的夏雨荷。

是的,这位"夏雨荷"就是cout<<。

cout有点类似C语言的printf函数,是C 里面负责标准输出的。不过又有不同,我们可以看到cout后面不是加括号,而是连接了<<这个特殊的符号。

暂时我们不深入,因为cout其实不是一个函数,cout是一个ostream类的对象(关于类和对象,之后的课程会讲解),它有一个成员运算符函数 operator<<(涉及到C 的运算符重载的技术,以后会讲)。(这一句指令暂时不需要理解,只要知道cout<<可以用来向屏幕输出内容即可)。

那么机智如你,应该猜到怎么显示变量的值了吧。

c基础教程第十讲(C探索之旅)(8)

是的,就是把文本替换成变量名就行了。如下:

cout << userAge;

这么简单,你敢信?

是的,就是这么简单。

#include <iostream>

using namespace std;

int main()

{

int userAge(16);

cout << "你的年龄是 : ";

cout << userAge;

return 0;

}

运行以上程序,显示:

你的年龄是 : 16

当然了,我们也可以同时显示好几个变量的值,并且把一句话的内容都写在一行上。如下:

#include <iostream>

#include <string>

using namespace std;

int main()

{

int userIQ(150);

string userName("Albert Einstein"); // 阿尔伯特.爱因斯坦

cout << "你名叫 " << userName<< ", 你的智商是 " << userIQ<< endl;

return 0;

}

运行以上程序,显示:

你名叫 Albert Einstein, 你的智商是 150

引用

在结束这一课之前,我们还有一个很重要的知识点需要介绍。

这个知识点就是:引用

《引用》的英语是reference。

我们之前说过,变量可以被看成内存里的一个“抽屉”。这个抽屉外面可以贴标签,就是变量名。

实际生活中,我们可以在同一个抽屉外面贴上不止一个标签。那么,在C 中,我们也可以给同一个内存的“抽屉”上贴好多个标签。

因此,我们就多了一种访问变量的方式。就好像我们给变量取一个别名。但是别名听起来没有那么高大上,所以C 中称之为“引用”。听着是不是挺玄乎的,其实就是别名。

我们可以用下图来演示:

c基础教程第十讲(C探索之旅)(9)

可以看到,在内存中的这个变量上,有两个标签。一个是userAge,声明此变量时起的变量名;另一个是myVariable,是它的别名,也就是引用。

比如,黄晓明,也可以叫小明,两个名字指代的都是那个人,都爱着Angelababy。

那么引用怎么声明呢?要用到一个特殊的符号:&

int userAge(16); // 声明一个变量,名字是userAge

int& myVariable(userAge); // 声明一个引用变量,名叫myVariable,它是userAge变量的别名。

可以看到,userAge放在了myVariable后面的括号里,还记得变量如何初始化吗?就是在括号里填入初始值。因此,这里相当于把userAge“赋值”给了myVariable

说到底,userAge和myVariable指向的是同一个“抽屉”,同一个变量。它们的值都是16。

用术语说就是:myVariable引用了userAge。

引用变量的类型必须和它要引用的变量一样。而且,引用变量声明时必须赋初值。

我们来看一个例子程序:

#include <iostream>

using namespace std;

int main()

{

int userAge(16); // 一个变量,名字是userAge,包含一个整型数值16

int& myReference(userAge); // 变量userAge的一个引用

// 从现在开始,我们可以不加区分地使用userAge或myReference

// 因为它们实际上是一个内存中“抽屉”的两个标签,指向的是相同内容

cout << "你已经 " << userAge << " 岁了. (通过 变量名)" << endl;

// 惯常的方式

cout << "你已经 " << myReference << " 岁了. (通过 引用)" << endl;

// 用引用的方式来访问变量值

return 0;

}

运行以上程序,显示:

你已经 16 岁了. (通过 变量名)

你已经 16 岁了. (通过 引用)

那么,引用到底有什么用呢?

好问题。在上面的例子中,仿佛看不出引用有多大用处。

也许暂时你觉得引用比较抽象,也貌似没什么用。但是要知道,引用是C 中很重要的一块知识点,而且以后我们会“大宝啊,天天见”,会经常使用到“引用”的。而且还会区分什么时候用引用,什么时候用指针。

因此,先对引用的概念有个了解,对我们之后处理更复杂的用例是大有裨益的。

总结

  1. 变量是存储在内存里的一段信息

  2. 根据存储的信息的不同,变量有不同类型:int,char,bool,double,等

  3. 变量在使用前需要先声明,例如:int number(28); // 此处是定义型声明

  4. 可以用cout来显示变量的值

  5. 引用其实是变量的别名,有点像标签,使我们可以用另一个名字来调用变量,例如:int& numberReference(number);

第一部分第五课预告

今天的课就到这里,一起加油吧!

下一课我们学习:简易计算器

程序员联盟ProgrammerLeague

官网和论坛

coderunity点com

coderunity点com/bbs/

frogoscar

邮箱:enmingx@gmail.com

,