科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件正确使用指针

正确使用指针

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

指针就是地址。 按类型来分指针有 int、char 、float等基本类型。

来源:中国软件网 2008年4月1日

关键字: 指针 使用 C++ C Linux

  • 评论
  • 分享微博
  • 分享邮件

指针就是地址。

按类型来分指针有 int、char 、float等基本类型。
对于扩充的数据类型则有struct 等。
指针的类型决定了指针操作时该指针指向地址变化的规律。
例: int a, *p; file://定义了一个整型指针以后就可以写为 p=&a; 这个好理解。
麻烦的是指针与数组结构等结合起来了之后情况就变得复杂起来,如下例:
int arr[10], *p; p=arr; 此时把数组的地址赋给了指针p,指针p就指向了数组的首地址。现在假设数组的首地址值是3452,则指针p的值必然是3452。那么 p+1 表示指针移动指向了数组的下一个元素,那么p+1的值是什么?初学指针时对这一点很容易搞错不加思索的回答既然p==3452,那么p+1就等于3452+1==3453,
如果这样去认识指针就大错特错了。这里的p+1不是简单的算术运算,它表示这样一个意思——指针移动了一个元素准确地说是指针移动了一个整型元素。一个整型变量占多少字节内存:2 个字节,所以在这里指针的地址变化为一个整型变量那么它的地址自然要在原来的地址值上加 2 ,所以指针移动一个整型元素后地址值应为3452+2,即指针p的值为3454。
上面讲的是整型指针的情形,对于字符型指针呢?其实只要对上面所讲的道理真正理解了,字符型指针也就好理解了。例子如下:
char aa[10], *p; p=aa; 同样假设数组的首地址为3452,那么p+1 的值可以这样考虑,指针移动一个字符的地址,而一个字符占一个字节的内存,所以p+1的值就为3452+1=3453。

可以说上面的二种情形还好理解,对于指向二维数组的指针以及指向结构的指针又如何去正确理解呢?

当指针与二维数组连在一起的时候情形就变得复杂了许多。因为数组名代表了
数组的起始地址,如 char arr[5][6]; 那么数组名 arr就是这个二维数组的首地
址。初学指针的朋友对这个问题总是弄不明白,既然二维数组名arr是一个地址,而
指针变量就是存放地址的,把二维数组的地址赋给同样数据类型的指针不就可以了
吗,于是就有这样的写法:char arr[5][6], *p; p=arr; 这样写肯定是错误的,有的
朋友可能对这样写是错误的也明白,他们基于这样的理解:一个二维数组里的数组
元素也是表示一个地址,于是得出结论,二维数组名是一个二级指针,是地址的地
址,进而引申出如下写法:
char arr[5][6]; char **p; p=arr; 然而很对不起,这样写同样是错误
的,如果你不相信,你可以把你认为正确的代码输入到里面,编译一下,肯定是通
不过的。

那么为什么上面的这些理解是错误的呢?错在对指针基本概念理解停留在表面。下
面为了把这个问题说清楚一点,我们可以把指针的类型归纳为二个特征:
1、基本数据类型如(char、int、 float等);
2、扩充数据类型(如一维数组、二维数组、结构等)
例1:
int arr[4][5]; file://定义了一个二维数组
int *p; file://定义了一个整型指针
// 下面该怎样把数组的地址赋给指针?因为定义的是一个int 指针,所以只能写为
p=arr[0]; file://想一想为什么?

这里要讲的就是把地址赋给指针时要注意的问题,p是 int 类型的指针,它只能指向 int 这个基本数据类型。有的朋友或许要问,这个二维数组不也是 int 类型吗?是的但是这个二维数组除了是 int 之外,它的类型全称应该是 int 二维数组,arr[0]是int 一维数组,arr[0]这个一维数组的各元素才是基本的 int 数据类型, p=arr[0]就是把这个一维数组第一个元素的地址赋给了int 类型的指针 p,. 数据类型完全一样才能赋值。那么显而易见可以有下面的写法,注意指针是怎样指向各数组元素的:
char arr[4][5]={"abc","def","ghi","jkl","mno"};
char *p=arr[0];
for(i=0;i<20;i++)
printf("%c", *(p+i) ); file://仔细观察输出的值是怎样变化的
file://因为定义的是一个字符型指针,那么1、必须使这个指针指向与其对应的字符型数
据类型; 2、指针每增加一个单位的地址值 ,如p+1表示指向下一个字符的地
址。所以printf()语句输出的结果为" abcdefghijklmno" ,是一个字符一个字符输出的。
。。
下面举一个整型指针的例子:
int arr[3][3]={ {1,2,3},{4,5,6},{7,8,9}};
int *p=arr[0]; file://数据类型相同,可以赋地址值
for(i=0;i<9;i++)
printf("%d", *(p+i)); // 逐个的输出数组元素

。。

下面将要讲的是直接指向一个二维数组的指针它有哪些特点:
一个二维数组,它的每一个数组元素都是一个一维数组,一个整型二维数组可以写为:
int arr[3][3]; 即 {arr[0], arr[1], arr[2] }
我们现在想定义一个指针,使得这个指针有这样的特性—— 指针 p指向arr[0],
指针 p+1 指向arr[1] ,指针 p+2指向arr[2], 也就是指针每移动一个单位的地址就指向下一个一维数组,那么这个指针必须满足下面二个条件:1、必须是整型 2、必须每移动一个单位的地址时实际上移动一个一维数组的长度即3个整型量。那么这个指针可定义为如下形式:
int (* p) [3] ; // 定义了一个指向二维数组的指针,这个二维数组中的一维数组有3个元素。
p=arr; // 把二维数组的地址赋给指针 p
如果二维字符数组初始化是 char arr[3][4]={"abc","def","ghi"};
所以可以如下写:
*(p+0) file://是数驵 a[0] 的首地址 printf("%s", *p); 输出字符串 “"abc"
*(p+1) file://数组a[1]的首地址 printf("%s", *(p+1)); 输出字符串 "def"
*(p+2) file://数组 a[2]的首地址 printf("%s",*(p+2)); 输出字符串 "ghi"

如果要用这个二维数组的指针逐个的输出字符可以写为:
*(*(p+0)+0) file://第一个字符 a
*(*(p+0)+1) file://第二个字符 b
*(*(p+0)+2) file://第三个字符 c
*(*(p+0)+3) file://第四个字符 d
*(*(p+0)+4) file://第五个字符 e
.................. 依此类推

当指针指向结构时的情形。。。

如果对指向数组的指针完全理解了,那么对指向结构的指针也就很好理解了。实际上一个指向结构的指针更容易理解。

设定义了一个结构如下,有一个结构数组,三个结构。
struct student{ int a;char *b;}stru[3]={{1,"abc"},{2,"def"},{3,"ghi"}};
struct student *p=stru;

p+0 file://第一个结构的地址
p+1 file://第二个结构的地址
p+2 file://第三个结构的地址

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章