文档章节

C Primer Plus 第10章 数组和指针 10.5 指针操作

idreamo
 idreamo
发布于 2016/07/30 07:01
字数 1610
阅读 77
收藏 0

C提供了6种基本的指针操作,下面的程序将具体演示这些操作。为了显示每一个操作的结果,程序将打印出指针的值(即指针指向的地址)、指针指向地址中存储的内容,以及指针本身的地址(如果您的编译器不支持%p说明符,那么想要打印出地址,就需要使用%u或者%lu)。

程序清单10.13示例了可对指针8种基本操作。除了这些操作,你还可以使用关系运算符来比较指针。

程序清单10.13  ptr_ops.c程序

//ptr_ops.c指针操作
#include <stdio.h>
int main(void)
{
    int urn[5]={100,200,300,400,500};
    int * ptr1,* ptr2,* ptr3;

    ptr1 = urn;  //把一个地址赋给指针
    ptr2 = &urn[2];  //同上
                     //取得指针指向的值,并且得到指针的地址
    printf("pointer value, dereferenced pointer, pointer address:\n");
    printf("ptr1 = %p,*ptr1 = %d,&ptr1 = %p\n",
           ptr1,*ptr1,&ptr1);
    //指针加法
    ptr3 = ptr1 + 4;
    printf("\nadding an int to a pointer:\n");
    printf("ptr1 + 4 = %p, *(ptr1+3)=%d\n",
           ptr1+4,*(ptr1+3));
    //递增指针
    ptr1++;
    printf("\nvalues after ptr1++\n");
    printf("ptr1 = %p,*ptr1 = %d,&ptr1 = %p\n",
           ptr1,*ptr1,&ptr1);
    //递减指针
    ptr2--;
    printf("\nvalues after ptr2--\n");
    printf("ptr2 = %p,*ptr2 = %d,&ptr2 = %p\n",
           ptr2,*ptr2,&ptr2);
    //恢复为初始值
    --ptr1;
    ++ptr2;
    printf("\npointers reset to original values:\n");
    printf("ptr1 = %p,ptr2 = %p\n",
           ptr1,ptr2);
    //一个指针减去另一个指针
    printf("\nsubtracting one pointer from another:\n");
    printf("ptr2 = %p, ptr1 = %p,ptr2 - ptr1 = %d\n",
           ptr2,ptr1,ptr2-ptr1);
    //一个指针减去一个整数
    printf("\nsubtracting an int from a pointer:\n");
    printf("ptr3 = %p, ptr3 - 2 = %p\n",
           ptr3,ptr3 - 2);
    return 0;
}

下面的列表描述了可对指针变量执行的基本操作:

** 赋值(assignment)---可以把一个地址赋给指针。通常使用数组名或地址运算符&来进行赋值。注意:地址应该和指针类型兼容。也就是说,不能把一个double类型的地址赋给一个指向int的指针。

** 求值(value - finding)或取值(dereferencing)---运算符*可取出指针指向地址中存储的数值。因此,*ptr1开始为100,即存储在地址0x0012ff38中的值。

** 取指针地址---指针变量同其他变量一样具有地址和数值,使用运算符&可以得到存储指针本身的地址。本例中,ptr1被存储在内存地址ox0012ff34中。该内存单元的内容是0x0012ff38,即urn的地址。

** 将一个整数加给指针---可以使用+运算符来把一个整数加给一个指针,或者把一个指针加给一个正数。两种情况下,这个整数都会和指针所指类型的字节数相乘,然后所得结果会加到初始地址上。于是ptr1+4的结果就等同于&urn[4]。如果相加的结果超出了初始指针所指向数组的范围,那么这个结果是不确定的,除非超出数组最后一个元素的地址能够确保是有效的。

** 增加指针的值 ---可以通过一般的加法或增量运算符来增加一个指针的值对指向某数组元素的指针做增量运算,可以让指针指向数组的下一个元素。因此,ptr1++运算把ptr1加上数值4(我们系统上int为4个字节),使ptr1指向urn[1]。现在ptr1的值是0x0012ff3c,*ptr1的数值为200。请注意ptr1本身的地址仍然是0x0012ff34。别忘了,变量是不会因为它的值的变化而移动位置的

** 从指针中减去一个整数 ---可以使用-运算符来从一个指针中减去一个整数指针必须是第一个操作数,或者是一个指向整数的指针这个整数都会和指针所指类型的字节相乘,然后所得到的结果会从初始地址中减掉。于是,ptr3-2的结果等同于&urn[2],因为ptr3是指向&urn[4]的。如果相减结果超出了初始指针所指向的数组范围,那么这个结果是不确定的,除非超出数组最后一个元素的地址能够确保有效。

** 减小指针的值---指针当然也可以做减量运算。请注意,你可以使用前缀或后缀形式的增量和减量运算符。

** 求差值(Differencing)---可以求出两个指针之前的差值。通常对分别指向同一个数组内的两个元素的指针求差值,以求出元素之间的距离差值的单位是相应类型的大小有效指针差值运算的前提是参加运算的两个指针是指向同一个数组(或是其中之一指向数组后面的第一个地址)。

** 比较---可以使用关系运算符来比较两个指针的值,前提是两个指针具有相同的类型

注意,这里有两种形式的减法。可以用一个指针减掉另一个指针得到一个整数,也可以从一个指针中减掉一个整数得到一个指针

在进行指针的增量和减量运算时,要牢记一些注意事项。计算机并不检查指针是否仍然指向某个数组元素。C保证指向数组元素的指针和指向数组后的第一个地址的指针都是有效的。

另外,可以对指向一个数组元素的指针进行取值运算。但不能对指向数组后的第一个地址的指针进行取值运算,尽管这样的指针是合法的

特别注意:不能对未初始化的指针取值

切记:当创建一个指针时,系统只分配了用来存储指针本身的内存空间,并不分配有来存储数据的内存空间。因此在使用指针之前,必须给它赋予一个已分配的内存地址。比如,可以把一个已存在的变量地址赋给指针。

指针的最初功能在于同函数交换信息。从前面所学的内容可知,如果需要让被调函数修改调用函数中的变量,就必须使用指针。

指针的另一个基本功能是用在处理数组的函数中。

© 著作权归作者所有

idreamo
粉丝 18
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
C Primer Plus 第10章 数组和指针 10.4 函数、数组和指针

假设您要编写一个对数组进行操作的函数,目的是要此函数返回数组内所有元素的和。假设marbles为这个int数组的名称。应该如何来调用这个函数? 一种合乎情理的猜测如下: totao = sum(marble...

idreamo
2016/07/28
59
0
C Primer Plus 第10章 数组和指针 10.3 指针和数组

我们举一个这种变相使用的例子:数组名同时也是该数组首元素的地址。也就是说,如果flizny是一个数组,下面的式子是正确的: flizny == &flizny[0] //数组名是该数组首元素的地址 flizny和&...

idreamo
2016/07/25
33
0
C++ primer第二次阅读学习笔记(第4章)

C++语言应尽量使用vector和迭代器类型,应避免使用低级的数组和指针,涉及良好的程序只有在强调速度时才在类实现的内部使用数组和指针。因此要向成为一个真正的C++程序员就要多使用vector和s...

长平狐
2012/10/08
74
0
C Primer Plus 第10章 数组和指针 编程练习答案

1、修改程序清单10.7中的程序rain,使它不使用数组下标,而是使用指针进行计算(程序中仍然需要声明并初始化数组)。 2、编写一个程序,初始化一个double数组,然后把数组内容复制到另外两个...

idreamo
2016/08/14
262
0
C Primer Plus 第10章 数组和指针 10.7 指针和多维数组

指针和多维数组有什么关系?为什么我们需要知道它们之间的关系?函数是通过指针来处理多维数组的,因此在使用这样的函数之前,您需要更多的了解指针。假设有如下的声明: int zippo[4][2] ; ...

idreamo
2016/08/06
68
0

没有更多内容

加载失败,请刷新页面

加载更多

怎样在磁盘上查找MySQL表的大小?这里有答案

导读 我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎。不应该在 INFORMATION_SCHEMA.TABLES 中提供这些信息吗?没那么简单! 我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎...

问题终结者
23分钟前
5
0
jQuery load() 方法实现加载远程数据

jQuery load() 方法是简单但强大的 AJAX 方法。load() 方法从服务器加载数据,并把返回的数据放入被选元素中。 语法: $(selector).load(URL,data,callback);必需的 URL 参数规定您希望加载的...

前端老手
25分钟前
3
0
Spring Boot缓存实战 Redis 设置有效时间和自动刷新缓存-2

问题 上一篇Spring Boot Cache + redis 设置有效时间和自动刷新缓存,时间支持在配置文件中配置,说了一种时间方式,直接扩展注解的Value值,如: @Override@Cacheable(value = "people#${s...

xiaolyuh
33分钟前
9
0
怎样在磁盘上查找MySQL表的大小?这里有答案

我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎。不应该在 INFORMATION_SCHEMA.TABLES 中提供这些信息吗?没那么简单! 我想知道 MySQL 表在磁盘上占用多少空间,但看起来很琐碎。不应...

Linux就该这么学
58分钟前
5
0
Redis

一、Redis支持的几种数据类型:字符串、List、SET、HASH、ZSET 二、Redis的缓存技术主要是为了降低关系数据库的负载并减少网站成本 三、在Redis里面,被MULTI命令和EXEC命令包围的所有命令会...

BobwithB
今天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部