如何在ie6下调试页面

ie6真心很不和谐啊,最近修改了一点主题的css样式,一直没发现有啥问题,今天心血来潮用ie6看了下,结果侧边栏居然错位了,无语了,搞了半天ie6又没有调试模式,哪里出的问题都不知道,纠结……

百度了半天,ie6调试css,结果一些工具下载链接都打不开了要么就找不到,简直不可思议.

难道ie6已经被彻底遗忘了么-_-!!

最终找到了一个叫做firebug lite的工具,没用过firefox,也不知道这个firebug lite和firefox上面著名的firebug是不是一家的……

不过这个东西真心很好用,在网页head里面引入一个js,就出现了类似chrome里面那样的调试界面!

调试了一下,终于解决了在ie6的显示问题,oh yeah!!

代码如下:

<script type="text/javascript" src="https://getfirebug.com/firebug-lite-debug.js"></script>

该代码加入到网站页面的head里面就行了,刷新页面,就出现了类似chrome的调试界面.
小技巧:要查看一个div应用了哪些样式,可以在在html里面找到该div的代码,点击id的值就行了,旁边的style里面就会显示出来,还可以实时修改,实时显示!

PHP设置时区

在用php调用腾讯微博api的时候,转换时间时发现时间不对,腾讯微博api返回的时间是格林威治标准时间,中国时区GMT+8,所以直接显示的时间比真实时间相差8小时.

php中可以使用date_default_timezone_set(“Etc/GMT”);来设定时区,这个是设定为格林威治标准时间

一些例子:

date_default_timezone_set(“Etc/GMT+8”); //这里比林威治标准时间慢8小时
date_default_timezone_set(“Etc/GMT-8”); //这里比林威治标准时间快8小时
date_default_timezone_set(‘PRC’);  //设置中国时区 ,中国使用这个就可以了

所有支持的时区可以在php官方网站的文档中看到!

PHP后台调用其他页面

有时候有个页面需要经常执行,比如备份或者更新缓存之类的操作,如果直接把代码写到主页,这样虽然每次访问就会执行,但是如果这个操作需要很长的时间的话,那么就会让页面打开非常慢,这种情况显然是不希望碰到的.

那么有没有办法打开页面就调用另一个页面,但是不需要等他返回信息呢?

也就是相当与我去敲别人门(调用页面),正常的流程我会等一会直到有人开门(返回结果)或者没人开门(超时).

然而现在我要敲完门就不管了直接走人……至于有没有人开门我不需要关心.^-^!!

问了一些人,也查了一些资料,得到了一个方法,使用fsockopen,向指定页面发送GET请求,然后不需要去读取返回内容!

//PHP CODE:
$fp = fsockopen($_SERVER["HTTP_HOST"], 80, $errno, $errmsg);
if(!$fp) {
    echo "$errstr ($errno)<br>rn";
} else {
    fputs($fp,"GET /index.php HTTP/1.0rnHost: $hostrnrn");
    fclose($fp);
}

加上一点简单的说明:
fsockopen 打开一个连接,主机$_SERVER[“HTTP_HOST”],即执行代码的服务器地址,端口 80,后面两个是错误信息.

如果连接成功,就向该主机的写入GET /index.php HTTP/1.0rnHost: $hostrnrn,这实际就是请求index.php页面,

然后关闭连接.

如果在fputs后面加fread,就可以看到返回的信息,即正常访问index.php看到的页面内容还有header信息!

wordpress显示腾讯微博信息

wordpress没有类似于微博的功能,只能发表文章,有时有个想法,或看到一个好句子或者想简洁的说说现在的状态,总不能全都是去发文章吧,于是想到了添加个类似微博的功能,一路坎坷,总算是完成了!!

接下来说说完成这个功能的经历:

1.最开始的想法是基于wordpress,完全独立做个简单微博功能,在数据库中添加一个微博的表,自己写发表和显示的功能.虽然说这样的难度不大,不过老是上wordpress来发表不太方便.而且以后维护好像也不方便,就放弃了这个方法.

2.利用腾讯微博的微博秀,这个最简单,腾讯微博开放平台可以申请,得到一个iframe页面,会显示微博信息,样式也可以设定,用了几天后实在受不了,连接速度实在太慢,这性能简直是在给腾讯抹黑啊…..再次放弃……

3.利用腾讯微博api,这个速度还不错,只是需要自己解析数据,可以返回json或者xml数据,于是准备用这种方法,不过我对js不了解,在获取远程数据上出了问题,于是打算用php实现,可是wordpress的widget不支持php代码,于是只能自己自定义一个widget来实现.

3.1首先是直接添加了一个自定义的widget,内部直接用php通过微博api获取微博的数据再显示出来,但是由于本站使用了wp super cache插件,这样的后果就是如果不刷新缓存文件,微博的信息就不会更新.

3.2于是想到widget的功能改为php获取信息后处理成可以显示的格式后保存到服务器上作为缓存文件,然后widget再用js的方式引用这个文件实现动态加载.由于本站还使用了wp minify插件,所以还得把这个js文件加入排除列表.于是这个功能就算是完成了!

3.3然后又考虑到了如果这个api调用速度问题,虽然现在看起来是很快,但是难保以后会不会出问题,于是想到了后台更新缓存文件.这暂时就是最终版.

具体流程就是自定义一个widget,他有两个工作,首先是使用后台的方法调用一个php页面,这个php页面负责更新缓存;再就是就是输出用js引用的方式调用缓存文件的代码.

然后辛苦完成了以后,悲剧了,这个功能可以简化,完全可以添加一个wordpress内置的文本widget,然后写上引用缓存文件的js代码就可以了,最后经过优化,写出了一个php文件,只需要在文本widget中用js引用调用这个php文件就可以完成信息加载和缓存的功能了.

附上该php代码:

//weibo.php
<?php
if($_GET["updata"]=="1"){
	date_default_timezone_set('PRC');
	$ch = curl_init("这里填写你的api url ,申请方法看下面") ;
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true) ; 
	curl_setopt($ch, CURLOPT_BINARYTRANSFER, true) ; 
	$json = json_decode(curl_exec($ch),true);
	$data= "<ul>";
	foreach($json[data][info] as $value){
	    if($value["text"]!=NULL){
	         $data.= "<li>".$value["text"]."<br/><font color=808080>".strftime("%Y-%m-%d %H:%M", $value[timestamp])."</font></li><hr>";
	    }
	}
	$data.= "</ul>";
	$data = "document.write("".str_replace(""", "\"", $data)."");";
	file_put_contents("weibo.cache",$data);
}else{
	echo file_get_contents("weibo.cache");
	$fp = fsockopen($_SERVER["HTTP_HOST"], 80, $errno, $errmsg);
	if(!$fp) {
		echo "$errstr ($errno)<br>rn";
	} else {
		fputs($fp,"GET $_GET[path]/weibo.php/?updata=1 HTTP/1.0rnHost: $hostrnrn");
		fclose($fp);
        }
}
?>

然后在文本widget中加入js代码:

<script type="text/javascript" src="主题路径/weibo.php/?path=主题路径"></script>

因为我把php文件放到主题目录里面了,所以上面需要加入主题路径,如果把php放到网站根目录,那么js代码就是:

<script type="text/javascript" src="/weibo.php"></script>

而weibo.php文件的代码也需要修改一处:

fputs($fp,"GET $_GET[path]/weibo.php/?update=1 HTTP/1.0rnHost: $hostrnrn");
//修改为
fputs($fp,"GET /weibo.php/?update=1 HTTP/1.0rnHost: $hostrnrn");

功能说明:

调用weibo.php后会读取目录下的weibo.cache文件,然后把它echo出来,之后weibo.php后台调用自己,不过加上了参数update=1,weibo.php发现update的值为1就会执行更新缓存weibo.cache的操作.

这个代码只是简单的显示了自己发的微博的文本内容,使用的api是https://open.t.qq.com/api/statuses/user_timeline?

完整的api请求可以到微博开放平台调试里面自动生成,API在线调试

步骤:

首先授权:

我选择的oAuth2.0授权(其他也可以,可能有些东西要改)

填入你自己的App Key 和 App Secret 确认授权,没申请应用的话暂时用这个页面默认的测试appkey也可以.

然后页面内填写:

fomat => json
reqnum => 填写你要拉取的微薄条数
name => 你要拉取的微博的id

然后点发送请求

下面有个header信息,GET后面 /api/statuses/user_timeline?….一直到HTTP/1.1 之间的部分记录下来,不包括HTTP/1.1
你的api地址就是https://open.t.qq.com/加上刚才记录的地址.
如果是另外两种授权方式就不是https , 而是http .

bug:

1.第一次读取会出错,因为读取在写入之前,所以是读的不存在的文件,刷新一次就正常显示了
2.同样由于先读后写,新的微博信息需要刷新2次才会显示.

之所以先读后写是为了避免一些问题,比如读的时候写操作还没完成……造成的这两个bug我觉得可以接受.

备选解决方案:

1.读取缓存前先判断缓存文件是否存在.

2.先写入缓存再读取显示.

另外在file_put_contents函数中可以加入LOCK_EX参数,锁定文件,避免可能发生的并发冲突,不过没测试锁定文件是否对读取造成影响,希望以后能找到更好的解决方案……

如果把缓存放到数据库,然后使用crontab定时更新缓存,这样缓存更新就和用户访问隔绝开了,应该是个比较好的解决方案!

wordpress文章加版权信息

虽然我一直赞成开源共享的精神,并且我自己也尽力这样做着,但是这也无法阻止我想要留名的小虚荣……

wordpress没有内置的版权功能,也许有插件可以实现,不过插件我是能不用尽量不用,于是想着自己靠代码完成.

首先分析问题,wordpress文章内容输出的代码是在主题里面的,虽然网上有很多教程教你怎么让文章加版权,但是莫名其妙的是基本都是仅限于特定主题,让你到那个文件改哪段代码,也许这样输出是官方文档的标准推荐的输出方式?所以是通用的??

不过很显然,我对wordpress的改造中发现这类修改法完全不适用,要么我没有该文件,要么有该文件但是文件内容和”教程”不符,如果这是标准推荐,那么我只能说是我运气实在太差,用的模版全是野路子?

没办法只好自己想办法搞定了,以上都是废话,下面才是正文^_^!!

首先把模版文件下载到本地,如果是直接从wordpress下载的应该是zip压缩包,没有的话自己到网站目录把主题打包下载下来,然后利用winrar的搜索功能(其他压缩软件一样可以)查找代码.

比如文章加版权,首先基本逻辑了解一下,找到文章内容输出的代码->在文章输出代码结束后加上自己的代码,即版权信息.

百度google什么的都可以,翻wordpress官方文档也可以,找到了主题中文章输出是用的the_content()函数,于是在主题的压缩文件内直接搜索该字符串,于是可能会发现一到两个文件包含该代码(也许更多),那么接下来就简单了,在每个文件的the_content()后面,加个

echo "版权信息";

就行了.

注意:也许并不是每个文件的the_content()函数都会使用到,因此建议的做法是,搜索到多个文件时,每次只修改一个文件,修改后,看文章内容是不是加入了,没有加入就恢复该文件,修改下一个文件,直到发现哪个文件的the_content()是在起作用的就好了,并不需要每个都改,因为也许有的the_content()是用来输出其他类型的东东,也许并不适合相同的版权信息.

下面附上本站主题修改过程:

首先下载了主题包renegade.2.1.2.zip,发现有三个文件有the_content()函数调用,分别在index.php,page.php,wide.php中,the_content()的后面依次加入版权信息的代码

//...
the_content();
echo "
<hr />
<table>
<tbody>
<tr>
<td><span style="color: #159519;">名称:";
the_title(); //调用当前文章标题
echo "地址:";
the_permalink(); //调用当前文章url
echo "
本文发表于<a title="下弦古月" href="http://devsk.com">下弦古月</a>的博客,转载请注明,谢谢</span></td>
</tr>
</tbody>
</table>
";
//...

最后发现实际只有index.php加入的代码起了作用,于是本次修改就算完成了,其他两个文件应该都是页面模版,大概是创建新页面时的模版,如果需要显示版权也一样可以加入.

其实个人觉得这篇文章讲的加版权本身意义不大,更重要的是讲了一个如何修改的方法,不仅仅用在wordpress,其他的地方一样可以用,我要修改一个东西,并不需要把他完全弄懂,只要知道自己要干什么,然后定位该功能的位置,仅仅修改局部就行了.当然了局部的做法就有局限性,比如当我加入了版权信息后,想修改样式,结果发现不起作用,原因是主题自带的css已经指定了样式,因此要修改样式也比较麻烦,所以能去完全搞懂自然更好了!!

用Google身份验证器给你的ubuntu加把锁

最近发现Google身份验证器不是一般的强大,什么都能用,看了下中文还没有教程,这里做个简单的教程。

1ubuntu上安装包,ubuntu官方都有这个包,直接运行以下命令

sudo apt-get install libpam-google-authenticator

2、下面根据自己的喜好选择下就好了,我个人都选的Y

3、再来就是绑定手机客户端了,先运行

google-authenticator

会出现一个QRcode,手机上添加一扫描就好了,最关键的有5行 emergency scratch codes” 这个找个地方保存下,以防你手机掉了,或者刷成板砖了,呵呵。

4、最后就是设置SSH login的时候加载google验证器,运行

sudo nano /etc/pam.d/sshd

在文件最后加一行

auth required pam_google_authenticator.so

再编辑下SSH 配置文件,运行

sudo nano/etc/ssh/sshd_config

找到 ChallengeResponseAuthentication 这行,改成

ChallengeResponseAuthentication yes

5、重启SSH,搞定🙂

sudo service ssh restart

再次登录你会发现输入完帐号密码,还要输入下Google验证器上的6个数字。(没功夫截图了,有时间,我会上下图🙂

本文转自 害羞哥 的博客

WIN8激活信息备份

ghost的方法就不用说了

直接备份激活信息:

1、win8激活后,备份以下路径文件夹 C:WindowsSystem32sppstore 文件夹(内含隐藏文件)

2、重装系统,记住必须是与激活时相同的版本(新系统的硬件信息,用户名、密码、计算机名等应与上述备份所属系统的设置一致,不一致的没试过)

3、管理员身份运行cmd 输入slmgr -upk回车(清除Key信息)

4、Win+R 运行 msconfig-boot-safe mode(设置安全模式启动,选择重启)

5、在safe mode下,管理员身份运行cmd 输入net stop sppsvc(关闭Software Protection)

6、在C:WindowsSystem32spp 文件夹下,用已备份的store文件夹覆盖该目录下的store文件夹;

7、Win+R, msconfig-boot-去掉safe mode选勾,正常启动。

硬盘分区计算原理

追求所谓完美分区的可以研究一下!
一般公式为:分区大小=(分区大小-1)×4+1024×分区大小
     如果按照以上硬盘分区公式(X-1)*4+1024*X=Y 其中X就是你想要得到的整数分区的数值,单位是G,Y是你分区时应该输入的数字,单位是M。
按照这样的计算方法:
5G=5136MB
10G=10276MB
15G=15416MB
20G=20556MB
30G=30836MB
40G=41116MB
30G以内,输入上面的数据,如10G你输入10276,在Windows资源管理器里面显示的刚好10.00GB,而在管理工具-磁盘管理界面显示就是10.04GB,如果是40G你输入41116,那么在Windows资源管理器里面显示的刚好40.01GB。
因此上面的计算公式还不是很准确。
最精确硬盘分区的算法如下(来自网络):
硬盘一般有255磁头,63扇区,故每柱面大小为:
512byte x 255 x 63=8225280bytes =7.84423828125 MB
如果要分40GB,那么要40x1024MB=40960MB
需要柱面数为40960÷7.84423828125=5221.66
取整数既为5222个柱面
应分M数为5222×7.84423828125=40962.6123046875MB
不管小数点后面几位都进1,也就是40963MB,windows就认为是40GB了。
这个方法NTFS和FAT32通用。
下面附10GB到200GB整10GB递增的精确计算结果:
10GB = 10245MB
20GB = 20482MB
30GB = 30726MB
40GB = 40963MB
50GB = 51208MB
60GB = 61444MB
70GB = 71681MB
80GB = 81926MB
90GB = 92162MB
100GB = 102407MB
110GB = 112644MB
120GB = 122888MB
130GB = 133125MB
140GB = 143362MB
150GB = 153606MB
160GB = 163843MB
170GB = 174088MB
180GB = 184324MB
190GB = 194561MB
     此精确分区结果,在管理工具-磁盘管理界面,和Windows资源管理器里面显示的是整数,10G就是10.00GB,20G就是20.00GB,40G就是40.00GB。

深入解析序列点

int i = 3;

i = i++;

cout << i;

结果是什么?有人可能会说是3,也有人可能会说是4,更多的人在骂出题的人白痴,但这语句究竟有何问题呢?未必每个人都清楚。

有些人也许马上会说,这是“未定义行为”。没错,这是一个典型的未定义行为。i = i++这个表达式合乎C++语法,能够顺利编译通过,但是执行的结果,标准说“未定义”。为什么是“未定义”,深究起来,要从序列点说起。

序列点是程序中这样的一些点:通俗地说,执行至此,之前的语句都已经彻底执行干净执行完了,之后的语句还完全没开始执行;更常见、更严谨但略晦涩的说法是,之前的语句对现场环境的改变已经全部完成,之后的语句对现场环境的改变还没有开始。啥是现场环境呢?就是程序执行到某一点的那个状态,包括变量的内容、文件的内容等。

这跟最开始那个例子有什么关系呢?关键的问题来了:标准规定,两个序列点之间,程序执行的顺序可以是任意的。没错,正如你猜的那样,C++标准规定一个完整的表达式结束之后有一个序列点,而例子中i = i++是位于两个序列点之间的。编译器可以先算完i++,再写结果给i,也可以先将i = i,再令i++.按前面的方法算,i先自增变为4,然后i++返回3,于是i被赋值为3;按后一种方法算,i先被赋值为3,随后自增变成4.标准说了,这两种处理方法,编译器你爱选那种就选哪种,随便。如果谁写的程序像这样依赖执行的顺序,让他自己哭去!

等等,有人要问了,++的优先级难倒不是高于=吗?显然应该先执行++啊。这里有个概念的问题,前一段说的编译器先算i = i,绝不是说令=的优先级比++还高了。如果那样的话,表达式将变成 (i = i)++,也就是i.operator = (i)。 operator ++,执行++的主体变成i = i这个表达式的返回值了。上一段所说的先计算i = i,实际上还是先计算i++,只不过是先返回了i的值,然后推迟了将i自增1的操作先去干别的(i = i)去了,回头再来给i自增1.

——“什么,你说先干别的就先干别的,凭什么!”

嗯,我再重复一遍,标准规定,两个序列点之间,程序执行的顺序可以是任意的。

——“不是吃饱了撑的嘛,标准搞这个干啥?严格按照顺序执行不就完了嘛”。

C++标准弄这么复杂自然是有道理的。C++是极为重视执行效率的语言,这样做给了编译器优化的空间。比如考虑

int j = i++;

如果非得把i++执行干净了再干别的,那就不得不 temp = i; i += 1; j = i; .如果允许编译器打乱顺序执行呢,直接 j = i; i +=1; 就好了,省了一个temp倒一次的过程。

多说一句,一些更高层的语言,不是像C++这种极为重视效率的,比如Java,上面的例子就完全没有问题。Java完全不允许你编译器乱搞,上面那个例子,在Java中一定是先把i++彻底执行干净了返回3,再进行赋值,赋值完之后不会再有别的操作了,所以结果一定是3.

如何避免由序列点造成的这种未定义行为,有一句经典但有点晦涩的编程规则:“在相邻的两个序列点之间,一个对象只允许被修改一次,而且如果一个对象被修改则在这两个序列点之间只能为了确定该对象的新值而读一次”。其实明白了序列点具体是怎么回事,这个规则应该就很容易明白了。由于序列点之间程序执行顺序不确定,一个对象被修改多次的话最后留下的是哪次的结果就不确定。另外如果一个对象同时存在读取和修改,只有根据读取的结果来修改才是合法的,否则就会出现是先改完再读还是先读完再改的混乱。

最后再说一下最新的C++2003标准中定义的序列点(详细说明请参考标准)

·完整声明之后

·完整表达式之后

·进入函数时与退出函数时

·|| && ?: , 四个操作符的第一个操作数之后

最后一个似乎有点奇怪,为啥 + – 操作符之前就没有序列点,|| &&之前就有呢?a+b之间没有序列点而a||b之间就有,不公平啊。

嗯,你猜的没错,是为了短路。

不过要是手建重载了默认的||和&&,他们可就视同普通函数,不会在第一个操作数之后有序列点了,切记。

本文引自 huiguixian 的博客

序列点

这篇文章大概会用到的术语有,序列点(sequence points),副作用(side effects)。

在C99标准文件5.1.2.3讲到了序列点问题,序列点的定义是一个程序执行中的点,这个点的特殊性在于,在这个点之前语句产生的所有副作用都将生效,而后面语句的副作用还没有发生。在这一点,所有的事都是肯定的,而在序列点间,不能肯定某一个变量的值已经稳定,所以总体说来C语言的序列点只是用来说明这一点的值是肯定的。如何理解呢?先讲一下什么是副作用。

一个表达式有一个值,而在写出这个表达式的时候可能只是想要取得这个表达式的值。但有些表达式会有副作用。而有些表达式没有副作用,有时候我们正是要利用表达式的副作用来工作。比如:

int a = 10;
int b = a; /* a这个表达式在这里没有副作用,这里只是想要取得 */
/* a这个变量的值10,而b = a这个表达式有副作用,它的 */
/* 副作用是使b的值改变成a的值。 */

这就是所谓的一个表达式的副作用。正是因为有了副作用,很多功能才得以完成。有些表达式既会产生一个值,也会产生副作用。如i++这个表达式既会产生一个值(它是i自增以前的值),也会产生副作用。

在一个序列点之间,连续两次改变,并且访问该变量,会带来问题,比如经典的:
int i = 1;
i = i++;

在一个序列点之间,改变了i的值,并且访问了i的值,它的作用是什么呢?是a[1] = 1;还是a[2] = 2呢?不确定,这种代码没有价值,并且老板肯定不会赏识你写出这么精简的代码,你会被开除的。

再比如更经典的:

int i = 1;
printf(“%d, %d, %dn”, i++, i++, i++);

i = 1;
printf(“%dn”, i++ + i++ + i++);

i = 1;
printf(“%dn”, ++i + ++i + ++i);

很多大学的C语言老师都会讲解这个问题,包括我的老师,在讲的时候笔者就没有弄明白,其实,这是一个不值得讲解的问题,这是在跟编译器较劲,不同的编译器可能会得出不同的结果(但是平常的编译器可能会得出相同的结果,让程序员私下总结错误的经验。),这种根据不同的实现而得出不同的结果的代码没什么用。i++ + i++ + i++只是一个表达式,在这个表达式的内多次访问了变量i,结果不确定。并且这又会引发另外一个有趣的问题,可能有人会认为在这条语句执行完成以后i自加了3次,那i肯定是4?这也不确定,可能很多编译器做得确实是4,但是,在C标准中有这样一条:当一个表达式的值取决于编译器实现而不是C语言标准的时候,其中所做的任何处理都会不确定。即,如果有一个编译器在i++ + i++ + i++这个表达式中只读取一次i的值,并且一直记住这个值,那么算第一个i++,因为i的值是1所以算出后i的值为2,再算第二个因为假设的是只读取一次i的值,那此时i的值还是1并且被加到2(因为没有经过序列点,所以i的值不能肯定为2),于是经过三次从1加到2的过程以后,最后i的值是2而不是期望的4,呵呵。

其实这要看编译器如何实现了,不过既然得看编译器如何实现,那这种代码也得被炒鱿鱼。

既然序列点这么重要,那现在就得讲讲一些重要的序列点了,这些重要的序列点要程序员自己平时总结。

1). 一个重要的序列点在完整表达式的结尾,所谓完整表达式就是指不是一个更大的表达式的子表达式的表达式,仔细理解。

int i = 1;
i++; /* i++是一个完整表达式 */
i++ + 1; /* i++就不是一个完整的表达式,因为它是i++ + 1这个完整表达式的一部分 */

具体的完整表达式的种类,可以查阅相关资料,C99的标准文档是一个不错的选择。

2). 逗号表达式。逗号表达式会严格的按照顺序来执行并且在被逗号分隔开的表达式之间有一个序列点,所以,前一个逗号表达式如果是i++,则后面的表达式可以肯定现在的值是原来的值加1(如果有溢出则另当别论)。如:

int i = 1;
i++, i++, i++;
printf(“%dn”, i);

现在的i肯定是4;

3). &&和||运算符。有一种短路算法来解决除法中的除0情况。如下

int a = 10;
int b = 0;

if (b && a/b) {
/* some code here */
}

其中在求b的值的时候会短路,即,a/b不会执行。因为b的值为0,这样可以放心的使用除法了。这两个运算符在使用的时候都可以当成一个序列点,如果前一个表达式的值已经可以认定这整个表达式的值为真或者为假,则后面的表达式没有必要再求值,是多余的。即如上面的a/b是多余的,不能求值,求值也会出错。它们之间的求值顺序是肯定的。

4). 条件运算符?:。在问号的地方也存在一个序列点,也没什么可讲。反正就是问号前后可以访问和改变同一个变量,并且这种访问是安全的。

最后,在一个表达式内的求值顺序没有固定顺序,还有一个表现是,如下:

funa() + funb() + func();

C语言标准没有规定这三个函数谁会先执行,如果对顺序有要求,可以用临时变量来缓解。

本文引自 东东的小窝