深入理解C语言的指针


深入理解C语言的指针

文章插图
 
指针是C语言的一个核心特色 , 它以一种统一方式对不同数据结构中的元素产生引用 。对于新手来说 , 指针总是会带来很多困惑 , 但其实指针的基本概念非常简单 。下面是一些指针和它们映射到机器代码的关键原则 。
1、每个指针都对应一个类型指针类型表明指针指向的是哪一类对象 。比如:
【深入理解C语言的指针】int *ip;
char **cpp;
变量ip是一个指向int类型对象的指针 , 而cpp指针指向的对象自身就是一个指向char类型对象的指针 。
通常 , 如果对象类型是T , 那么指针的类型为T* 。特殊的void *类型代表通用指针 。比如malloc函数返回一个通用指针 , 然后通过显式强制类型转换或赋值操作的隐式强制类型转换 , 将它转换成一个有类型的指针 。
指针类型不是机器代码中的一部分 , 它是C语言提供的一种抽象 , 帮助程序员避免寻址错误 。
2、每个指针都有一个值指针的值是某个指定类型的对象的地址 。特殊的NULL(0)值表示该指针没有指向任何地方 。
3、用“&”创建指针“&”运算符可以应用到任何value类的C表达式上 , value类指可以出现在赋值语句左边的表达式 , 包括变量、结构和数组的元素 。
4、用“*”间接引用指针“*”运算符用于间接引用指针 , 其结果是一个值 , 它的类型与该指针的类型一致 。间接引用是用内存引用来实现的 , 要么是存储到一个指定的地址 , 要么是从指定的地址读取 。
5、数组与指针紧密联系一个数组的名字可以像一个指针变量一样引用(但不能修改) 。数组引用(a[3])与指针间接引用(*(a+3))有一样的效果 。
数组引用和指针运算都需要用对象大小对偏移量进行伸缩 。如表达式 p+i , 这里的指针p的值为p , 得到的地址计算为 p+L*i , 这里的L是与p相关联的数据类型的大小 。
6、指针的类型转换改变指针运算的伸缩将指针从一种类型强制转换成另一种类型 , 只改变它的类型 , 而不改变它的值 。强制类型转换的一个效果是改变指针运算的伸缩 。
比如p是一个char *类型的指针 , 它的值为p , 那么(int *)(p+7)的结果为 p+7 , 而(int *)p+7的计算结果为p+28 。
PS:强制类型转换的优先级高于加法 。
7、指针也可以指向函数这里指针提供了一个强大的存储和向代码传递引用的功能 , 这些引用可以被程序的其他部分调用 。
比如有一个函数定义如下:
int fun(int x, int*p);
然后可以声明一个指针fp , 将它赋值给这个函数 , 
int (*fp)(int , int *);
fp = fun;
然后就可以用这个指针来调用这个函数:
int y = 1;
int result = fp(3, &y);
函数指针的值是该函数机器代码表示中第一条指令的地址 。
函数指针声明的语法对新手程序员比较难以理解 , 对于以下声明:
int (*f)(int*);
要从里往外读 , 即从(*f)开始 , f是一个指针 , 而(*f)(int *)表明f是一个指向函数的指针 , 这个函数以一个 int *作为参数 。最后我们看到 , 它是指向以 int *为参数并返回int的函数的指针 。




    推荐阅读