C语言中的指针
2016-11-09 14:23
197 查看
指针概念
指针是一个变量,该变量的数值是地址,或者说,指针是一个数据对象。类似于,int 类型变量的数值是整数。
与指针相关的运算符
间接运算符:*
ptr 指向 bath,ptr = &bath。
获取 bath 中存放的数值,
val = * ptr。
上面两句语句等价于
val = bath。
地址运算符:&
后跟一个变量名时,&给出该变量的地址。
指针声明
int * pi;
int表明被指向的变量的类型是整型,
*表示该变量是一个指针。
pi所指向的值
(*pi)是
int类型,
pi的
类型是“指向 int 的指针”。
*和指针名之间的空格是可选的。
指针的输出格式是
%p。
使用指针在函数间通信
结合 PHP 中函数的引用赋值来理解。变量的值在函数中改变还是全局改变。
指针和数组
概念
在 C 中,对一个指针加 1 的结果是对该指针增加 1 个存储单元(storage unit)。对数组而言,地址会增加到下一个元素的地址,而不是下一个字节。归纳如下:
指针的数值就是它所指向的对象的地址。对于包含多个字节的数据类型,对象的地址通常是指其首字节的地址。
在指针前运用运算符
*可以得到该指针所指向的对象的数值。
对指针加1,等价于对指针的值加上它所指向的对象的字节大小。
函数、数组和指针
声明数组参量
下面的四种原型都是等价的int sum(int *ar, int n); int sum(int *, int); int sum(int ar[], int n); int sum(int [], int);
定义函数时,下面两种形式等价
int sum(int * ar, int n) { } int sum(int ar[], int n) { }
声明形式参量时,
int *ar和
int ar[]都表示
ar是指向
int的指针。
sizeof求变量、指针、数组大小。
使用指针参数
使用数组形参的函数需要知道数组的起点和终点。告知终点有两种方法,一种是直接使用整数参量指明数组元素的个数,一种是用指针指明数组的结束地址。比如,
int sum(int * start, int * end);
若数组的元素个数是
SIZE,那么,
* end的值是
&start + SIZE(表示数组的最后一个元素后面的下一个元素)。
一元运算符
*和
++具有相等的优先级别,但它在结合时是从右向左进行的。
指针操作
指针基本操作
赋值(assignment)。通常使用数组名或地址运算符
&进行地址赋值。地址应该和指针类型兼容。
求职(value-finding)或取值(dereferencing)。
取指针地址。
将一个整数加给指针。
增加指针的值。
从指针中减去一个整数。
减小指针的值。
求差值(Differencing)。指向同一个数组内两个元素的指针使用此运算。
比较。两个指针具有相同的类型。
对未初始化的指针取值
不能对未初始化的指针取值。例如int * pt; // 未初始化的指针 *pt = 5;
合法的代码
int i = 5; int * pt = &i;
或者
double * ptd; ptd = (double)malloc(30 * sizeof(double));
指针和多维数组
例程
#include <stdio.h> int main(void) { int zippo[4][2] = {{2, 4}, {6, 8}, {1, 3}, {5, 7}}; printf(" zippo = %p, zippo + 1 = %p\n", zippo, zippo + 1); printf("zippo[0] = %p, zippo[0] + 1 = %p\n", zippo[0], zippo[0] + 1); printf(" *zippo = %p, *zippo + 1 = %p\n", *zippo, *zippo + 1); printf("zippo[0][0] = %d\n", zippo[0][0]); printf(" *zippo[0] = %d\n", *zippo[0]); printf(" **zippo = %d\n", **zippo); printf(" zippo[2][1] = %d\n", zippo[2][1]); printf("*(*(zippo+2) + 1) = %d\n", *(*(zippo+2) + 1)); return 0; }
代码见
E:\code\c\c_primer_plus_c\10_15_zippo1.c。
这段代码中的疑点:
*zippo[0]、
**zippo。
声明指向二维数组的指针变量
正确的代码int (* pz)[2]; // 声明一个指向二维数组pz [2]的指针
错误的代码
int * pax[2]; // 创建一个两个指针的数组
指针兼容
int n = 5; double x; int * pi = &n; double * pd = &x; x = n; // 隐藏的类型转换 pd = pi; // 编译时错误
假如有如下声明:
int * pt; int (*pa)[3]; int ar1[2][3]; int ar2[3][2]; int **p2; // 指向指针的指针
那么,有如下结论:
pt = &ar1[0][0]; // 都指向int pt = ar1[0]; // 都指向int pt = ar1; // 非法 pa = ar1; // 都指向int[3] pa = ar2; // 非法 p2 = &pt; // 都指向 int * *p2 = ar2[0]; // 都指向int。不理解 p2 = ar2; // 非法。不理解
保护数组内容
对形参使用 const
如果不打算在函数中修改数组,在函数原型和函数定义中对参数使用const可以达到目的。例程如下:
int sum(const int ar[], int n); int sum(const int ar[], int n) { int i; int total = 0; for(i = 0; i < n; i++) total += ar[i]; return total; }
使用了
const,在函数中试图修改使用了
const的参数时,编译时会发现此错误。
有关 const 的其他内容
使用 const 创建符号常量。const double PI = 3.14159;
指向常量的指针不能用于修改数值,但可以指向其他地址。
double rates[5] = {88.99, 100.12, 59.45, 183.11, 340.5}; const double * pd = rates; // pd指向数组开始处 * pd = 29.89; // 不允许 pd[2] = 222.22; // 不允许 rates[0] = 99.99; // 允许,因为 rates 不是常量 pd++; // 让pd指向rates[1],允许
将常量或非常量数据的地址赋给指向常量的指针是合法的。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5}; const double locked[4] = {0.08, 0.075, 0.0725, 0.07}; const double * pc = rates; // 合法 pc = locked; // 合法 pc = &rates[3]; // 合法
只有非常量数据的地址才可以赋给普通的指针。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5}; const double locked[4] = {0.08, 0.075, 0.0725, 0.07}; double * pnc = rates; // 合法 pnc = locked; // 非法 pnc = &rates[3]; // 合法
使用 const 保证指针不会指向别处。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5}; double * const pc = rates; // 指针指向数组的开始处 pc = &rates[2]; // 不允许 *pc = 92.99; // 可以
使用 const 禁止修改所指向的数据。
double rates[5] = {88.99, 100.2, 59.45, 183.11, 340.5}; const double * const pc = rates; // 指针指向数组的开始处 pc = &rates[2]; // 不允许 *pc = 92.99; // 不允许
参考资料
《C Primer Plus(第五版)中文版》指针简介: P236-9.7
指针和数组: P254-10.3
函数、数组和指针: P256-10.4
指针操作: P260-10.5
指针和多维数组: P267-10.7
保护数组内容: P263-10.6
相关文章推荐
- C/C++语言void及void指针深层探索
- 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化
- c语言指针
- C/C++语言void及void指针深层探索
- C 语言中的好基友 数组和指针之一
- C 语言中的好基友 数组和指针之二
- c语言指针的形式参数
- 学习C/C++语言:指针与多维数组
- C语言中指针的使用
- C/C++语言void及void指针深层探索
- C语言技巧--在结构体中使用函数例子(定义一个指向函数的指针)
- c 语言指针的相关概念
- C/C++语言 void 及 void 指针深层探索
- C/C++语言void及void指针深层探索(转)
- C语言之指针专题三:理解指针要和内存四区模型和函数调用模型相结合
- 一句话C系列:C语言指针内幕
- GO语言结构体方法跟结构体指针方法的区别
- C/C++语言void及void指针深层探索
- C语言学习7-1:使用6级指针访问一个整数,使用隐式内存分配中转,约瑟夫环
- Go 语言指针