C++ 变量作用域小探索

 

最近开始学习C++, 刚好看到作用域这一块儿,遇到一些好像跟C不一样的地方(或者是一样的,,只是以前没注意罢了),比如说定义嵌套覆盖。。

写了一个小例子

 

#include

int num1 = 1;
std::string str1 = "David";

//display the value of str1
void display();

int main()
{
std::cout << "before definiton in main, num1 is " << num1 << std::endl; int num1 = 2; std::cout << "after definition in main, num1 is " << num1 << std::endl; std::cout << "before definiton in main, str1 is " << str1 << std::endl; display(); int str1 = 3; std::cout << "after definition in main, str1 is " << str1 << std::endl; display(); int num2 = 4; std::cout << "first declaration in main, num2 is " << num2 << std::endl; //std::string num2 = "Daisy"; //compile error:conflicting declaration //int num2 = 5; //compile error:redeclaration //statement scope for(int num1 = 0, sum = 0; num1 < 1; num1++) { sum += num1; std::cout << "num1 is " << num1 << std::endl; } std::cout << "num1 is " << num1 << std::endl; //statement scope for(int num2 = 0, sum = 0; num2 < 2; num2++) { sum += num2; std::cout << "num2 is " << num2 << std::endl; } std::cout << "num2 is " << num2 << std::endl; //block scope { std::string str1 = "Daisy"; std::cout << str1 << std::endl; display(); } std::cout << str1 << std::endl; } void display() { std::cout << "in display() str1 is " << str1 << std::endl; }

 

 

然后输出结果是

 

1.首先对于num1这个变量,已经在第三行定义成了全局变量并初始化为1,然后在main函数里第11行,打印输出很显然就是

“before definiton in main, num1 is 1”

然后我们在第12行把它重新定义一下,赋值为2,在第13行里打印出的结果就是

"after definition in main, num1 is 2"

惊讶了一下,居然可以这样用(或许是我以前没有这么写过C吧,不知道在C里面是否也可以这样用,忘记测试了)。对于已经定义了的变量,再定义一次,难道不会引起重复定义错误吗??那编译器不会迷惑吗?但是结果很显然的摆在那里,没有错误,并且结果也是预想的结果。

我就在想,会不会是因为类型一样,所以编译器忽略这些什么的。。。然后就想了一个比较BT的招儿,那就是把类型也给他换了,只保证名字一样,看结果如何。这就出现了第二个测试点。

 

2.对于在第四行第一次定义的string变量 str1,赋值为“David”。在main函数里第15行打印一下,很显然结果是

"before definiton in main, str1 is David", 就如同结果图片里面的第三行输出。

接着我调用了一下display()函数,主要是打印一下str1这个全局变量,结果也很显然是

"in display() str1 is David"

好了,现在我在第17行,重新定义了一下str1,这次不止改变了值,连类型也改变了,把它定义为了int并赋值为3,而全局变量是string类型的。然后打印,编译器没有报错,正常打印。

“after definition in main, str1 is 3”,然后我又调用了一下displays()函数,想看看是不是全局变量的也改变了,打印结果是

"in display() str1 is David",说明全局变量并没有被改变!

 

通过第1和第2两点,我总结了一下。全局变量虽然它的作用域是全局,但是在函数里面可以被屏蔽(不知道该找什么形容词),也就是说如果函数里面没有重新定义这个全局变量,那么对该变量的使用跟正常使用变量没什么区别。但是如果在函数里面重新定义了该变量,不管类型是不是一样,那么在二次定义以后,该函数对其的使用则是使用其重新定义以后的变量,但是这种使用并不改变全局变量,只是全局变量暂时被屏蔽了而已。

 

然后我在想,是不是只有全局变量可以这样被二次定义,然后就做了第三个试验

3.在main函数里第21行,定义了一个int变量num2,赋值为4,然后打印一下。结果很显然是

"first declaration in main, num2 is 4"

接着我试着在后面重新定义一下num2,首先把它的类型改变,编译,果断报错,“冲突的定义”。

然后我在想,是不是太激进了,于是只改变其值,不改变类型,但是不是直接赋值,而是重新定义一下并赋值。如24行所示。编译,果断报错,“重复定义”。

通过测试点3,说明了在同一作用域里的变量是不能重复定义的,只能定义一次。这个倒很正常,,,,因为写C的时候,这些都很熟悉了,只是前面遇到了“屏蔽”的情况,所以想顺道测试一下是不是同一作用域下也能“屏蔽”。

既然做都做了,那么也顺便测试一下语句作用域的情况吧,不是还有个叫statement scope的作用域么,于是有了测试点4

4.首先在一个循环里面,重新定义一下num1,我想,既然可以从“外”往“里”屏蔽,那么从“里”往“里的里”也应该能屏蔽,果然,在for里面,num1的值是在语句作用域里的值,跳出循环以后,再打印就是函数作用域里的num1值了(不是全局的值,它已经被main里的屏蔽,这点从打印的是2 而不是 1就看得出来)

然后测试了一下num2,这个结果就很显然了,既然“外”到“里的里”都都能屏蔽,那么只过度了一层的“里”到“里的里”,显然也能成功,打印结果也显而易见。

接着很蛋疼的测试了一下,直接用花括号包含起来的块作用域(能不能这么称呼啊。。。),把str1重新定义为了“Daisy”,然后打印,结果是“Daisy”,说明屏蔽成功,然后调用display()函数,打印的是“in display() str1 is David”,说明全局变量并没有被改变,那么对于str1的重定义是改变的什么呢,我觉得就是改变的main函数里的str1啦,我们在main函数里把str1重新定义为了int类型,然后在这个块里面,我们又屏蔽了这个int的定义,然后用string重新定义了。但是出了这个块以后,回到了main函数作用域,那我们打印str1的时候,当然又回到了main函数作用域里对他的定义,那就是int类型,并且值为3.

 

好啦,总结完毕,也对作用域有了更一步理解,,,其实说得挺模糊的。。。嘎嘎。

 

 

ssh连接godaddy

在godaddy那里为网站添加了SSL,其实主要是买SSL它会送一个独立IP,共享IP太容易被封了(独立的貌似也挺容易。。)。添加以后发现ftp好像登录不上去了,于是想用SSH去访问,不然我咋传文件啊,去网站传太慢了。

在命令行输入命令以后,居然提示我

“This account is currently not available.”

google了一下,发现是没有开启SSH。于是跑去godaddy,登录自己的账户,在web hosting下有一个SSH,就在这里激活。

但是它需要给你的手机发一个PIN码,你输入手机号的时候,记得加86,代表天朝~

输入完以后,点激活,半分钟就会有一个电话打过来,告诉你3个数字,然后输入到相应位置,就OK啦。

号码好像是+0001901212

return -1 为何echo $? 是255

今天在看C++, 书上说在命令行输入 echo $? 可以访问main函数的返回值来查看系统状态。一般来说我们main不是返回0嘛,返回其他值就是告诉系统错误,返回就返回了,也没有去注意。

突然想看看return -1的时候系统状态值是不是真的-1,结果发现echo $?以后,显示的是255!不是-1!

上网google了一下,发现系统的状态值是0-255,然后,当然return -1 再echo $?的时候就是255啦,同理如果返回-2的话就是254啦。

算是一个小知识。。记录一下~~~~~~

 

 

 

 

Linux改变文件目录字符集编码

最近遇到一个问题,就是把文件从windows通过SSH上传到linux服务器以后,在web页面浏览这些文件的时候,中文出现乱码。

到处搜搜,解决了,记录一下,方便以后要用的时候好找。大致是因为windows使用的GBK来编码中文字符,而linux用的是utf-8吧,所以只要转换一下格式就行了,于是搜了一下命令。

命令格式:convmv -f [原始编码] -t [目标编码] -r(目录循环)  –notest(实际改变,否则只是测试) [操作路径、文件]

如: convmv -f GBK -t UTF-8 -r –notest  upnp-related/  将  当前目录/upnp-related/下所有的目录和文件名由GBK改为UTF8格式。

如下图所示

然后再在web页面访问的时候就不是乱码啦

 

 

 

同一页面跳转不同位置

前段时间灏君突然问到那种同一页面跳转到不同位置是怎么实现的。当时没有想到该怎么做,后来在研究UPnP的时候,发现UPnP的介绍网站也有类似效果,如下面给出的例子。

同一页面上,跳转到不同位置,例子

http://developer.gnome.org/gupnp/unstable/glossary.html#state-variable

http://developer.gnome.org/gupnp/unstable/glossary.html#action

于是乎看了一下他的源代码,发现其实实现起来并不难,就是对“<a></a>”这一组标签的小应用。自己写了一个小demo测试一下。代码如下。

[html]
<html>
<head>
</head>
<body>
<a name="one"></a><!–作为到1的跳转标记–>
<p>
this is text <font color="red">one</font>
, <a href="test.html#two">goto_two</a><!–跳转去2–>
, <a href="test.html#three">goto_three</a><!–跳转去3–>
</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<a name="two"></a><!–作为到2的跳转标记–>
<p>
this is text <font color="red">two</font>
, <a href="test.html#three">goto_three</a><!–跳转去3–>
, <a href="test.html#one">goto_one</a><!–跳转去1–>
</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>

<a name="three"></a><!–作为到3的跳转标记–>
<p>
this is text <font color="red">three</font>
, <a href="test.html#one">goto_one</a><!–跳转去1–>
, <a href="test.html#two">goto_two</a><!–跳转去2–>
</p>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br>
</body>
</html>

[/html]

 

最后的效果如如下,一开始是这样的

点击 goto_two 以后,则跳到同一页面的,test two所在位置,如下图所示

点击 goto three,类似效果,或者点击goto one又回到顶端。

好像也正好可以用到开源软件协会的社员管理平台上去,让用户登录以后直接跳转到自己所在的位置。想想那个如何实现。

 

碎碎念

 

实在不知道想表达的主题是啥,就叫做碎碎念吧。

十一宅在寝室好几天了,想来也不要太辜负了这个假期,虽然外面拥堵,但作为北大荒的大兴,嗯,情况还是相当不错的。

正好今天大家都出去吃饭去了,寝室就剩下我一个人,也就没有了去食堂吃饭的欲望。想想那就一个人出去吃点儿啥吧,周围也没什么地方可去,可供选择的也就绿地缤纷城那边了,正好想起了想拍一下那座房子来着,也需要采购一些日用品。越想越觉得今晚是个该出去走走的日子,嗯,心情也随之好了不少,那就先锻炼锻炼然后洗个澡出发吧!

省略1024个字儿以后,好像是7点,都收拾好了,出发。很久没有散步了,走过去吧,正好校门口也没有黑车,晃晃悠悠就到了那边,拿出相机一顿咔嚓,好在已经不用看说明书了(囧。。。。依然随包携带)。看见两个玩轮滑的哥们儿从身边飘过,果断抓下来,由于没拍好,就不放上来了。

饿了,到下面的披萨店点了一份6寸的个人披萨吃,外加一份巧克力布朗宁甜点。本来想是不是拍下来,以前老在网上看到他们用微距拍的美食图片,那是相当诱惑啊。后来想了想还是算了,对于美食我还是吃的欲望大于拍,除非是不好吃的,二者才可能调换位置,但是不好吃的不也就更没拍的欲望了。思维有些混乱了,跳出去。

哈,还有最后一项没做呢。出来以后去逛了几圈超市,买了些东西,看到几个大美女,回到寝室,看到大美妞发的QQ,惊了一下,看了一下,回了。然后想着纪念纪念,又不知道该纪念什么,碎碎念一下今天的行程不正好么?想着,于是有了此文祸害人间。

UPnP linux新手入门

上次发了一篇关于UPnP的入门教程,也不算教程吧,就是介绍了一下新手该从哪里下手,但基本是基于Windows的。但是发现里面的例子好复杂,常常一个sample中一个文件就几百上K行代码,着实累。后来经郭大神介绍,去找了linux下的一个例子,感觉舒服多了,还是C看正清晰明了啊。

——————————————————————割——————————————————————————

首先可以到google搜一下gupnp,会发现这个网站https://live.gnome.org/GUPnP/ 这里有很多关于GUPnP的文档可以下载,这个可以选择下或者不下,最主要的是先把GUPnP这个库的源码下下来。如下图所示。

 

点击here就跳转到下载页面了。你会看到一个下载列表,由于东西太多,所以在页面上搜索一下gupnp,结果如下图所示。

选择最后一个 gupnp/ ,进入到另一个下载列表里面,这里有gupnp的各个版本,一般就选最新的好来,我们选0.18版本。

然后下一个页面是选择次版本号,也选最新的吧,0.18.4,然后点击最后一个下载就行了。

 

下到本地以后,解压缩。然后从终端进入gupnp-0.18.4目录,里面有一个examples目录,那里面是一个upnp-light的小例子。但是并没有Makefile文件,但是有Makefile.am 和Makefile.in。退回到gupnp-0.18.4目录来,可以看到有一个configure的可执行程序,运行它,就可以用Makefile.in生成Makefile了,如下图所示。

 

再进到examples目录底下,就可以发现有light-server 和 light-cilent可执行文件了。

先运行light-server,再运行light-client就可以看到效果,再结合light-server.c和light-client.c源代码就基本能弄清楚UPnP的大致工作流程了。

 

现在老张交给的工作就只剩下怎么把UPnP集成到现有的智能家居里面去了,囧