为何不精通C? 02 C语言中的符号重载,优先级

本文主要将两个部分,符号重载和运算优先级问题,这两个问题很常见,很繁琐。我猜绝大部分的人在学习时都选择性忽略该章节的内容。但是在面试时,却常常考这方面的东西,因为,“精通”之名。  


    C中,具备着符号重载,符号重载是体现在程序上下文语境中,不同符号表现出不同的含义。比如“*”,具备三个含义:声明指针,指针解引,乘号。 《C专家编程》总结了下所有的符号重载,用以理清C语言作用域规则:

符号 意义

static

函数内部:表示仅在首次调用声明该变量,在此后调用中保持传承
函数定义:该函数仅在本文件中可见
extern 函数定义:表示全局可见(默认属性,extern可省略)
变量声明:仅说明该变量在其他地方定义。
void 函数返回值: 不返回任何值
参数表:表示没有参数
指针声明:通用指针
* 乘号
声明:表示是一个指针
调用:取指针所指的值
& 调用:取该变量地址
位操作:与操作符
= 赋值符
== 比较运算符
<=
<<=
小于等于
左移复合赋值运算符
< 比较:小于号
#include 的左定界符,搜索从环境变量路径开始
() 函数定义中:包围形参表
调用一个函数
强制类型转换
改变运算顺序
定义带参数的宏
包围 sizeof操作符的操作数(类型名)

优先级

       实践中碰到了一堆操作符,怎么办?最佳tips:

  • 仅记住乘除运算优先于加减
  • 剩下的全部加括号

但是,要想精通C, 必须能够看懂别人写的代码,所以,一些优先级的常识还是需要巩固。注:关于声明部分的优先级,可以参考后续博文

优先级问题 表达式 人们可能的误解 实际的含义
 . 的优先级高于*,
因此实践中用“->”代替
*p.f p所指对象的成员f;
(*p).f
对p取f偏移,作为指针,然后解引操作;
*(p.f)
[]优先级高于* int* p[] p是指向int数组的指针;
int(*p)[]
p是一个存储元素类型为int* 的数组;
int*(p[]);
函数()优先于* int* fp() fp是一个函数指针,该函数返回int;
int (*fp)()
fp是一个函数,返回 int*
int* (fp())
==和!=高于位操作符 (val&mask != 0) (val&mask)!=0 val&(mask!=0)
==和!=高于赋值符 c=getchar()!=EOF (c=getchar()) != EOF c=(getchar()!=EOF)         c为真假
算术符优于移位 msb<<4+lsb (msb<<4)+lsb msb<<(4+lsb)
逗号优先级最低 i=1,2 i=(1,2) (i=1),2                         2被抛弃

总结下次序吧:

  • 初等运算 () [] -> .
  • 单目运算 
  • 算术  先乘除模,再加减
  • 移位
  • 关系   先 大小,再 等不等
  • 位   同逻辑一样,都是 先与 后或
  • 逻辑 (不包括!,因为它是单目)
  • 条件
  • 赋值
  • 逗号

通常来说,结合性都是与优先级配合使用的,但是常见课本中一大堆凌乱的表示,让人眼花缭乱,整体来看,所有的结合性规则可以归结成以下两句话:

  • 所有的赋值符 都具有右结合性。 何为赋值符呢,我的理解是 “真实调用时,是否改变
  • 剩下的,都是左结合性

举例解释我对改变的理解

1、意变

  • !p :这是逻辑非操作符,在调用时,改变了p的值
  • *p:指针操作符,真是调用的是p所指东西,而不是p本身,真是调用发生了改变
  • &a : 取地址,真正调用是a的地址,而不是a,真是调用发生了改变
  • sizeof a: 调用时,返回a的字节长度,而不是a本身,调用发生了改变

以上意变其实都是属于单目运算符的部分

2、值变

  • ++i: 调用后i值改变
  • is?true:false: 调用后,is发生了改变
  • is?true:false: 调用的返回结果不确定,某种意义上,调用的是一个“改变”的东西  谢谢 求道于盲 指出。
  • 赋值运算符:=, += 之类,调用后,值发生了改变

总结:更多的,还是按着直觉走,要记的,就是那些不走寻常路的,另外,我觉得改变部分凝练得还行,^_^

posted @ 2013-05-17 11:14  xield  阅读(528)  评论(2编辑  收藏  举报