函数调用符、聚合访问符、单目操作符综合学习
1.简介:
操作符的学习是我们日常学习C语言时遇见的第一个重点内容,在很多书中,操作符的学习章节在书的前半部分就完成了,讲的比较抽象,一般我们能学到聚组符,算术运算符,比较运算符,赋值运算符,如果认真的学习,还可能会学习到 &&, ||, ?: , 这四个控制操作符,不然的话,只有在 % 符号上找成就感了,因为剩下的符号的运用都将集中在本章后。所以这些知识必须在学完指针、数组、函数、结构后,再次学习。
那么抛开前面说的聚组,算术运算符,比较运算符,赋值运算符,控制操作符,还剩下函数调用符,聚合访问符,单目操作符,位运算(也是算术运算符)。而这几天我就参考《C与指针》这本书综合学习了它们。
2.操作符:
1. 聚组 ( expression )
2. 函数调用 ( option_list )
3. 聚合数据访问 [] . ->
4. 单目操作符 (右)++ (右)--
! ~ + - * ++(左) --(左) & sizeof (类型)
上表从上到下, 优先级由高至低。
第 1,2,3,4 行, 结合性由左向右。
第 5 行, 结合性由右向左。
3. 预备知识:
1> 源代码的组成: 由标识符、32个关键字、28个符号、字面值常量和若干个空白符组成的文本文件。
2> 什么是标识符: 变量,函数,类型的名称。
3> 什么是声明标识符:声明就是告诉编译器,此标识符是什么类型,占多大内存空间。
4> 什么是定义标识符:定义就是让系统为该标识符分配合理的内存空间。
总结: 1>定义标识符的同时也会产生一份该标识符的声明。
2>对于已定义的静态标识符,可以在多处进行重声明。
3>对于已定义的动态标识符,其声明仅在定义时完成,不能重声明。
4>在代码中,调用标识符的位置前,必需得有它的声明。
4. 标识符的声明:
理解: 声明一个标识符并不是我们所想的那样直观----告诉编译器将一个标识符声明成某种类型。
而是用该标识符与多个符号和类型关键字组合成一条语句,编译器阅读该语句后推测出标识符的类型。
说明: 标识符的声明其实就是聚组符,函数调用符,聚合数据访问符,单目运算符的综合运用。
例: 1> int a;
标识符 a 是int类型数据。
1> int *a,
对标识符 a 间接访问后是一个int类型数据。
a是指向int的指针。
2> int a[20],
对标识符 a 的第20个元素下标访问,得到是int型数据。
a是指向整型的指针常量。
定义时分配20个int型内存空间,a初始化为该空间首数据地址
3> char *str[15] ,
对标识符 str 的第15个元素下标访问后再间接访问,得到一个char型数据。
str是指向字符指针的指针常量。
定义时连续分配了15个字符指针类型内存空间,str初始化为该空间首数据地址。
4> char (*str)[15],
对str间接访问后,再对第15个元素下标访问,得到一个char型数据。
str是一个指针,指向的是一个长度为15的字符数组。
定义时分配了1个指向长度为15个字符数组的指针空间。
5> char **str,
对str间接访问两次后,得到一个char型数据。
str是指向字符指针的指针变量。
定义时分配1个指向字符指针的指针类型空间。
6> double (*oper_func[5])( double, double );
对oper_func的第5个元素下标访问后再间接访问是一个必须接收两个double形参数且返回double型数据的函数
oper_func是指向函数指针的指针常量。
定义时分配了5个指向函数的指针空间,oper_func初始化为该空间的首数据地址。
7> int *func( void *value );
调用func函数接收一个指针形参,对返回值间接访问得到一个int型数据
func是一个函数名,返回值是整型的指针
8> int *(*cmp)( void *a1, void *a2 );
对cmp间接访问,函数接收两个指针形参,对返回值间接访问得到一个int型数据
cmp就是一个指向函数的指针,返回值是整型指针。
5. 指针的移动:
说明: 遍历数组型数据结构时,会综合运用了三个单目操作符( * ++ --)。
当遇见 ++ -- 时,表答式中运用的都是其所操作数据的一份拷贝。
例: 1> *spt++
获得一份spt的拷贝,spt指向下一个数据, 间接访问拷贝的spt指针。
2> *++spt
spt指向下一个数据,获得一份spt的拷贝,间接访问spt指针。
3> ++*spt
间接访问spt指针,将访问到的数据加1并获得一份该数据的拷贝。
4> (*spt)++
间接访问spt指针并获得一分该数据的拷贝,将访问到的数据加1。
5> --*spt++
获得一份spt的拷贝,spt指向下一个数据,间接访问拷贝的spt指针,将访问至的数据减1并获得一份该数据的拷贝。
6.其它综合运用:
说明: 这个版块主要是为了证明单目运算符的结合性是从右到左的。
例: 1> int a, b, *&c;
a = *&b;
先对 c 取地址,再对该地址间接访问,得到一个整型数据。
那么 c 就是一个整型数据。
2> int a = 10, b, c ;
b = ~a--;
c = ~--a;
首先得说明书上的一点问题:
书中将 ~ 符号称之求补符号,但是它的过程是求反码,因为补码等于反码加 1 。a = 0XA, ~a = 0XFFFFFFF5, 当我们以十进制打印出~a时,因为a 是有符整型值,故要经过取返、加1、添负号这个过程,所以值为-11。
b = ~a--; 取到一份 a 的数据拷贝; 将 a 的值减1; 对拷贝取反并赋与 b。
c = ~--a; 把a的值减1;取到一份a的数据拷贝;对拷贝取反并赋与c。
注: b = 0XFFFFFFF5 = -11, c = 0XFFFFFFF7 = -9 ( 这里考虑了--的负作用 )
3> int a, b, c = 5;
a = - --c; 把c的值减 1,取到一份 c 的拷贝,对该拷贝求负并赋与a。
b = -c--; 取到一份 c 的拷贝,把 c 的值减1,对拷贝求负并赋值与b。
-- -c 与 (-c)--是非法的,因为 ++ 与-- 的操作数必须是一个左值。