没有合适的资源?快使用搜索试试~ 我知道了~
C语言学习口诀.doc
1星 需积分: 10 15 下载量 47 浏览量
2009-08-14
16:11:16
上传
评论 2
收藏 133KB DOC 举报
温馨提示
试读
21页
简明易懂, 真是老太太和小孩子都一学就会. 好歹也写了多年的程序, 随手东施效颦, 模仿了个c语言的口诀, 一步一步写程序, 类型结构加数据. 指针运算先赋值, 条件循环后排序. .......
资源推荐
资源详情
资源评论
C 语言运算符的“优先级口诀”
优先决
括号成员第一; //括号运算符[ ] ( ) 成员运算符. - >
全体单目第二; //所有的单目运算符比如++ -- +(正) -(负) 指针运算*&
乘除余三,加减四; //这个"余"是指取余运算即%
移位五,关系六; //移位运算符:<< >> ,关系:> < >= <= 等
等于(与)不等排第七; //即== !=
位与异或和位或; //这几个都是位运算: 位与(&)异或(^)位或(|)
"三分天下"八九十;
逻辑或跟与; //逻辑运算符:|| 和 &&
十二和十一; //注意顺序:优先级(||) 底于 优先级(&&)
条件高于赋值, //三目运算符优先级排到 13 位只比赋值运算符和","高//需要注意的是赋值运算符很多!
逗号运算级最低! //逗号运算符优先级最低
由于 C 语言的运算符优先级与 C++的不完全一样(主要是增加了几个运算符),所以这个口诀不能完全实用于 C++.但是应
该能够兼容,大家可以比较一下他们的区别应该就能够很快掌握 C++的优先级的!
位运算应用口诀
清零取反要用与,某位置一可用或
若要取反和交换,轻轻松松用异或
移位运算
要点 1 它们都是双目运算符,两个运算分量都是整形,结果也是整形。
2 "<<" 左移:右边空出的位上补 0,左边的位将从字头挤掉,其值相当于乘 2。
3 ">>"右移:右边的位被挤掉。对于左边移出的空位,如果是正数则空位补 0,若为负数,可能补 0 或补 1,这取决于
所用的计算机系统。
4 ">>>"运算符,右边的位被挤掉,对于左边移出的空位一概补上 0。
位运算符的应用 (源操作数 s 掩码 mask)
(1) 按位与-- &
1 清零特定位 (mask 中特定位置 0,其它位为 1,s=s&mask)
2 取某数中指定位 (mask 中特定位置 1,其它位为 0,s=s&mask)
(2) 按位或-- |
常用来将源操作数某些位置 1,其它位不变。 (mask 中特定位置 1,其它位为 0 s=s|mask)
(3) 位异或-- ^
1 使特定位的值取反 (mask 中特定位置 1,其它位为 0 s=s^mask)
2 不引入第三变量,交换两个变量的值 (设 a=a1,b=b1)
目 标 操 作 操作后状态
a=a1^b1 a=a^b a=a1^b1,b=b1
b=a1^b1^b1 b=a^b a=a1^b1,b=a1
a=b1^a1^a1 a=a^b a=b1,b=a1
二进制补码运算公式:
-x = ~x + 1 = ~(x-1)
~x = -x-1
-(~x) = x+1
~(-x) = x-1
x+y = x - ~y - 1 = (x|y)+(x&y)
x-y = x + ~y + 1 = (x|~y)-(~x&y)
x^y = (x|y)-(x&y)
x|y = (x&~y)+y
x&y = (~x|y)-~x
x==y: ~(x-y|y-x)
x!=y: x-y|y-x
x< y: (x-y)^((x^y)&((x-y)^x))
x<=y: (x|~y)&((x^y)|~(y-x))
x< y: (~x&y)|((~x|y)&(x-y))//无符号 x,y 比较
x<=y: (~x|y)&((x^y)|~(y-x))//无符号 x,y 比较
应用举例
(1) 判断 int 型变量 a 是奇数还是偶数
a&1 = 0 偶数
a&1 = 1 奇数
(2) 取 int 型变量 a 的第 k 位 (k=0,1,2……sizeof(int)),即 a>>k&1
(3) 将 int 型变量 a 的第 k 位清 0,即 a=a&~(1<<k)
(4) 将 int 型变量 a 的第 k 位置 1, 即 a=a|(1<<k)
(5) int 型变量循环左移 k 次,即 a=a<<k|a>>16-k (设 sizeof(int)=16)
(6) int 型变量 a 循环右移 k 次,即 a=a>>k|a<<16-k (设 sizeof(int)=16)
(7)整数的平均值
对于两个整数 x,y,如果用 (x+y)/2 求平均值,会产生溢出,因为 x+y 可能会大于 INT_MAX,但是我们知道它们的平均
值是肯定不会溢出的,我们用如下算法:
int average(int x, int y) //返回 X,Y 的平均值
{
return (x&y)+((x^y)>>1);
}
(8)判断一个整数是不是 2 的幂,对于一个数 x >= 0,判断他是不是 2 的幂
boolean power2(int x)
{
return ((x&(x-1))==0)&&(x!=0);
}
(9)不用 temp 交换两个整数
void swap(int x , int y)
{
x ^= y;
y ^= x;
x ^= y;
}
(10)计算绝对值
int abs( int x )
{
int y ;
y = x >> 31 ;
return (x^y)-y ; //or: (x+y)^y
}
(11)取模运算转化成位运算 (在不产生溢出的情况下)
a % (2^n) 等价于 a & (2^n - 1)
(12)乘法运算转化成位运算 (在不产生溢出的情况下)
a * (2^n) 等价于 a<< n
(13)除法运算转化成位运算 (在不产生溢出的情况下)
a / (2^n) 等价于 a>> n
例: 12/8 == 12>>3
(14) a % 2 等价于 a & 1
(15) if (x == a) x= b;
else x= a;
等价于 x= a ^ b ^ x;
(16) x 的 相反数 表示为 (~x+1)
C 语言缺陷与陷阱(笔记)
C 语言像一把雕刻刀,锋利,并且在技师手中非常有用。和任何锋利的工具一样,C 会伤到那些不能掌握它的人。本文介绍
C 语言伤害粗心的人的方法,以及如何避免伤害。
第一部分研究了当程序被划分为记号时会发生的问题。第二部分继续研究了当程序的记号被编译器组合为声明、表达式和
语句时会出现的问题。第三部分研究了由多个部分组成、分别编译并绑定到一起的 C 程序。第四部分处理了概念上的误
解:当一个程序具体执行时会发生的事情。第五部分研究了我们的程序和它们所使用的常用库之间的关系。在第六部分
中,我们注意到了我们所写的程序也许并不是我们所运行的程序;预处理器将首先运行。最后,第七部分讨论了可移植性
问题:一个能在一个实现中运行的程序无法在另一个实现中运行的原因。
词法分析器(lexical analyzer):检查组成程序的字符序列,并将它们划分为记号( token)一个记号是一个由一个或多
个字符构成的序列,它在语言被编译时具有一个(相关地)统一的意义。
C 程序被两次划分为记号,首先是预处理器读取程序,它必须对程序进行记号划分以发现标识宏的标识符。通过对每个宏
进行求值来替换宏调用,最后,经过宏替换的程序又被汇集成字符流送给编译器。编译器再第二次将这个流划分为记号。
1.1= 不是 ==:C 语言则是用=表示赋值而用==表示比较。这是因为赋值的频率要高于比较,因此为其分配更短的符
号。C 还将赋值视为一个运算符,因此可以很容易地写出多重赋值(如 a = b = c),并且可以将赋值嵌入到一个大的表达
式中。
1.2 & 和| 不是&& 和||
1.3 多字符记号
C 语言参考手册说明了如何决定:“如果输入流到一个给定的字符串为止已经被识别为记号,则应该包含下一个字符以组成
能够构成记号的最长的字符串” “最长子串原则”
1.4 例外
组合赋值运算符如+=实际上是两个记号。因此,
a + /* strange */ = 1
和
a += 1
是一个意思。看起来像一个单独的记号而实际上是多个记号的只有这一个特例。特别地,
p - > a
是不合法的。它和
p -> a
不是同义词。
另一方面,有些老式编译器还是将=+视为一个单独的记号并且和+=是同义词。
1.5 字符串和字符
包围在单引号中的一个字符只是编写整数的另一种方法。这个整数是给定的字符在实现的对照序列中的一个对应的值。而
一个包围在双引号中的字符串,只是编写一个有双引号之间的字符和一个附加的二进制值为零的字符所初始化的一个无名
数组的指针的一种简短方法。
使用一个指针来代替一个整数通常会得到一个警告消息(反之亦然),使用双引号来代替单引号也会得到一个警告消息
(反之亦然)。但对于不检查参数类型的编译器却除外。
由于一个整数通常足够大,以至于能够放下多个字符,一些 C 编译器允许在一个字符常量中存放多个字符。这意味着
用'yes'代替"yes"将不会被发现。后者意味着“分别包含 y、e、s 和一个空字符的四个连续存储器区域中的第一个的地址”,
而前者意味着“在一些实现定义的样式中表示由字符 y、e、s 联合构成的一个整数”。这两者之间的任何一致性都纯属巧合。
2 句法缺陷
理解这些记号是如何构成声明、表达式、语句和程序的。
2.1 理解声明
每个 C 变量声明都具有两个部分:一个类型和一组具有特定格式的、期望用来对该类型求值的表达式。
Foat *g(), (*h)();
表示*g()和(*h)()都是 Foat 表达式。由于()比*绑定得更紧密,*g()和*(g())表示同样的东西:g 是一个返回指 Foat 指针的
函数,而 h 是一个指向返回 Foat 的函数的指针。
当我们知道如何声明一个给定类型的变量以后,就能够很容易地写出一个类型的模型( cast):只要删除变量名和分号并
将所有的东西包围在一对圆括号中即可。
Foat *g();
声明 g 是一个返回 Foat 指针的函数,所以(Foat *())就是它的模型。
(*(void(*)())0)();硬件会调用地址为 0 处的子程序
(*0)(); 但这样并不行,因为*运算符要求必须有一个指针作为它的操作数。另外,这个操作数必须是一个指向函数的指针,
以保证*的结果可以被调用。需要将 0 转换为一个可以描述“指向一个返回 void 的函数的指针”的类型。(Void(*)())0
在这里,我们解决这个问题时没有使用 typedef 声明。通过使用它,我们可以更清晰地解决这个问题:
typedef void (*funcptr)();// typedef funcptr void (*)();指向返回 void 的函数的指针
(*(funcptr)0)();//调用地址为 0 处的子程序
2.2 运算符并不总是具有你所想象的优先级
绑定得最紧密的运算符并不是真正的运算符:下标、函数调用和结构选择。这些都与左边相关联。
接下来是一元运算符。它们具有真正的运算符中的最高优先级。由于函数调用比一元运算符绑定得更紧密,你必须写 (*p)()
来调用 p 指向的函数;*p()表示 p 是一个返回一个指针的函数。转换是一元运算符,并且和其他一元运算符具有相同的优
先级。一元运算符是右结合的,因此*p++表示*(p++),而不是(*p)++。
在接下来是真正的二元运算符。其中数学运算符具有最高的优先级,然后是移位运算符、关系运算符、逻辑运算符、赋值
运算符,最后是条件运算符。需要记住的两个重要的东西是:
1. 所有的逻辑运算符具有比所有关系运算符都低的优先级。
2. 移位运算符比关系运算符绑定得更紧密,但又不如数学运算符。
乘法、除法和求余具有相同的优先级,加法和减法具有相同的优先级,以及移位运算符具有相同的优先级。
还有就是六个关系运算符并不具有相同的优先级:==和!=的优先级比其他关系运算符要低。
在逻辑运算符中,没有任何两个具有相同的优先级。按位运算符比所有顺序运算符绑定得都紧密,每种与运算符都比相应
的或运算符绑定得更紧密,并且按位异或(^)运算符介于按位与和按位或之间。
三元运算符的优先级比我们提到过的所有运算符的优先级都低。
这个例子还说明了赋值运算符具有比条件运算符更低的优先级是有意义的。另外,所有的复合赋值运算符具有相同的优先
级并且是自右至左结合的
具有最低优先级的是逗号运算符。赋值是另一种运算符,通常具有混合的优先级。
2.3 看看这些分号!
或者是一个空语句,无任何效果;或者编译器可能提出一个诊断消息,可以方便除去掉它。一个重要的区别是在必须跟有
一个语句的 if 和 while 语句中。另一个因分号引起巨大不同的地方是函数定义前面的结构声明的末尾,考虑下面的程序片
段:
struct foo {
int x;
}
f() {
...
}
在紧挨着 f 的第一个}后面丢失了一个分号。它的效果是声明了一个函数 f,返回值类型是 struct foo,这个结构成了函数
声明的一部分。如果这里出现了分号,则 f 将被定义为具有默认的整型返回值[5]。
2.4 switch 语句
C 中的 case 标签是真正的标签:控制流程可以无限制地进入到一个 case 标签中。
看看另一种形式,假设 C 程序段看起来更像 Pascal:
switch(color) {
case 1: printf ("red");
case 2: printf ("yellow");
case 3: printf ("blue");
}
并且假设 color 的值是 2。则该程序将打印 yellowblue,因为控制自然地转入到下一个 printf()的调用。
这既是 C 语言 switch 语句的优点又是它的弱点。说它是弱点,是因为很容易忘记一个 break 语句,从而导致程序出现隐
晦的异常行为。说它是优点,是因为通过故意去掉 break 语句,可以很容易实现其他方法难以实现的控制结构。尤其是在
一个大型的 switch 语句中,我们经常发现对一个 case 的处理可以简化其他一些特殊的处理。
2.5 函数调用
和其他程序设计语言不同,C 要求一个函数调用必须有一个参数列表,但可以没有参数。因此,如果 f 是一个函数,
f();
剩余20页未读,继续阅读
资源评论
- lwyltx682013-04-03"C语言学习口诀"是有个人之处,但组成口诀并不好记,前提是你必须有C语言基础之后,才知道口诀的实际含意,否则将是空谈,另外,口诀比较长,不易诵记,要上口,则必费点劲不可,这是个人意见,谢!
h8285953
- 粉丝: 44
- 资源: 25
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功