本文总结对符号用法的相关讨论。
2010-10-20 wcdj
本文接:Dissection C Chapter 1_3
http://blog.csdn.net/delphiwcdj/archive/2010/10/18/5948666.aspx
1,注释符号
2, 续行符和转义符
3,单引号、双引号
4,逻辑运算符
5,位运算符
6,花括号
7,++、--操作符(CSDN上常见的月经贴)
8,表达式2/(-2)的值是多少?
9,运算符的优先级
下面总结这部分内容需要注意的一些知识点。
1,注释符号
【问题1】C语言的注释可以出现在C语言代码的任何地方吗?
编译器会将注释剔除,但不是简单的删除,而是用空格代替原来的注释。因此,下面的注释[4]是不正确的:
#include <cstdio> int main() { // [1], ok int/*...*/i; // [2], ok char* s="abcd //efgh"; // [3], ok, note that there is no blank after '/'(backslash) character // Is it a / valid comment? // [4], error, because it equals to " in t i; " in/*...*/t i; return 0; }
【注意】/*...*/这种形式的注释不能嵌套。因为/*总是与离它最近的*/匹配。
/*This is/*wrong*/*/
【问题2】y=x/*p;正确吗?
y=x/*p,这是表示x除以p指向的内存里的值,把结果赋给y吗?我们在编译器上测试一下,发现出错。
原因是:实际上,编译器把/*当作是一段注释的开始,把/*后面的内容都当作注释内容,直到出现*/为止。这个表达式其实只是表示把x的值赋给y,/*后面的内容都当作注释,但是,由于没有找到*/,所以提示出错。修改方法为:
(1) y=x/ *p;// 在'/'符号后添加至少一个空格符
(2) y=x/(*p);// 或者添加括号
修改后,表达式的意思才是,x除以p指向的内存里的值,最后把结果赋给y了。
【注意】只要斜杠(/)和星号(*)之间没有空格,都会被当作注释的开始。
【问题3】怎样才能写出出色的注释?(糟糕的注释只会帮倒忙)
2, 续行符和转义符
【注意】反斜杠(/)(续行符)之后不能有空格。
反斜杠除了可以被用作续行符,还能被用作转义字符的开始标识。
广义地讲,C语言字符集中的任何一个字符均可用转义字符来表示。即用:
/ddd 1~3位八进制数所代表的字符
/xhh 1~2位十六进制数所代表的字符
ddd和hh分别为八进制和十六进制的ASCII码。如:/102表示字母'B'(66,dec.),/134表示反斜线,/X0A表示换行,/X0D表示回车等。
3,单引号、双引号
【注意】表示方式不一样,所占的内存大小也不一样。
1,'1',"1"
第一个是整型常数,32位系统下占4B大小。
第二个是字符常量,占1B大小。
第三个是字符串常量,占2B大小(包括字符串结束符('/0'))。
【注意】字符在内存里是以ASCAII码存储的,所以字符常量可以与整型常量或变量进行运算。如:'A'+1。
4,逻辑运算符
【注意】||和&&是逻辑运算符,|和&是按位运算符。
【注意】小心“短路规则”。
5,位运算符
C语言中位运算包括下面六种:
& 按位于
| 按位或
^ 按位异或(p^q=~p*q+p*~q)
~ 取反
<< 左移
>> 右移
【注意】用异或^运算符可以实现对两个数的交换。(想想,交换两个整数有几种方法?异或,中间变量,先加后减,……)
【问题1】左移和右移
[1] 左移运算符"<<"是双目运算符。其功能是把"<<"左边的运算数的各二进制位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。
[2] 右移运算符">>"是双目运算符。其功能是把">>"左边的运算数的各二进制位全部右移若干位,由">>"右边的数指定移动的位数。
但注意:对于有符号数,在右移时,符号位将随同移动。当为正数时,最高位补0;而为负数时,符号位为1,最高位是补0还是1取决于编译系统的规定。Turbo C和很多系统规定为补1。
【问题2】0x01<<2+3的值为多少?结果为7吗?
// warning C4554: “<<”: 检查运算符优先级可能存在的错误;使用圆括号阐明优先级 (VS2008提示)
int ival=0x01<<2+3;// 32
因为"+"号的优先级比移位运算的优先级高。
思考:下面的行为正确吗?(发生了溢出!)
// warning C4293: “<<”: Shift 计数为负或过大,其行为未定义
int ival2=0x01<<2+30;// VS2008下为
// warning C4293: “>>”: Shift 计数为负或过大,其行为未定义
int ival2=0x01>>2+30;// VS2008下为
// warning C4293: “>>”: Shift 计数为负或过大,其行为未定义
int ival3=0x01>>2-3;// VS2008下为
结论:左移和右移的位数不能大于数据的长度,而且不能小于0,否者其行为未定义。
6,花括号
【问题】花括号的作用是什么?
char a[10]="abcd";
char b[10]={"abcd"};
//char c[10] { ="abcd" };// error
简单地说,花括号的作用就是:打包,使其中的语句成为一个整体,并与外界绝缘。
7,++、--操作符(CSDN上常见的月经贴 -_- !)
【问题】下面的结果是什么?
int i=3, j;
j=(++i)+(++i)+(++i);// j==18 (VS2008)
int i=3, j;
j=(++i)+(++i)+(++i);// j==18 (VC6.0)
j的值是多少呢?15、16、18吗?
其实对于这种情况,C语言标准并没有作出规定。
VS2008的计算过程是:i先经过3次自加后变为6,然后3个6相加得18。
VC6.0的计算过程是:先计算前两个i的和,这个时候i自加2次,2个i的和为10,然后再加上第三次自加的i得16。
8,表达式2/(-2)的值是多少?
#include <cstdio> int main() { int ival0=(-2)/2; // -1 int ival1=2/(-2); // -1 int ival2=2%(-2); // 0 equals to 4%2 int ival3=(-2)%2; // 0 equals to -(2%2) int ival4=3%(-3); // 0 equals to 6%3 int ival5=(-3)%3; // 0 equals to -(3%3) int ival6=2%(-3); // 2 equals to 5%3 int ival7=(-3)%2; // -1 equals to -(3%2) int ival8=5%(-2); // 1 equals to 7%2 int ival9=(-2)%5; // -2 equals to -(2%5) return 0; }
大多数编译器要求:余数与被除数的正负号相同。
9,运算符的优先级
【一些容易出错的优先级问题】
[1] .的优先级高于*,*p.f相当于*(p.f)
[2] []高于*,int *ap[]相当于int *(ap[]),是一个指针数组
[3] 函数()高于*,int *fp()相当于int *(fp()),是一个函数
[4] ==和!=高于位操作,(val & mask != 0)相当于val & (mask != 0)
[5] ==和!=高于赋值符,c=getchar()!=EOF相当于c=(getchar()!=EOF)
[6] 算术运算符高于位移运算符,msb<<4+lsb相当于msb<<(4+lsb)
[7] 逗号运算符在所有运算符中优先级最低,i=1, 2相当于(i=1), 2