深入理解C指针1.3  指针操作符_深入理解C指针1.3  指针操作符试读-查字典图书网
查字典图书网
当前位置: 查字典 > 图书网 > 编程 > 深入理解C指针 > 1.3  指针操作符

深入理解C指针——1.3  指针操作符

指针有几类操作符。目前我们已经接触过解引和取地址操作符,本节将近距离研究指针算术运算和比较。表1-4 总结了指针操作符。 表1-4:指针操作符 1.3.1  指针算术运算 数据指针可以执行以下几种算术运算: • 给指针加上整数; • 从指针减去整数; • 两个指针相减; • 比较指针。 函数指针则不一定。 1. 给指针加上整数 这种操作很普遍也很有用。给指针加上一个整数实际上加的数是这个整数和指针数据类型对应字节数的乘积。 各个系统的基本数据类型长度可能不同,正如1.2.1 节所述。表1-5 显示了大部分系统的常见长度,除非特别指定,本书的示例会使用这里的值。 表1-5:数据类型长度 为了说明给指针加上整数的效果,我们会使用一个整数数组,如下所示。每次pi 加1,地址就加4。这些变量的内存分配如图1-7 所示。指针是用数据类型声明的,以便执行算术运算。这种自动调整指针值的可移植方法之所以可能,前提就是知道数据类型的大小。 int vector[] = {28, 41, 7}; int *pi = vector; // pi: 100 printf("%dn",*pi); // 显示28 pi += 1; // pi: 104 printf("%dn",*pi); // 显示41 pi += 1; // pi: 108 printf("%dn",*pi); // 显示7 如果这里使用数组的名字,返回的只是数组地址,也就是数组第一个元素的地址。 图1-7:vector 数组的内存分配情况 在下面的代码中,我们给指针加3,pi 变量会包含地址112,就是pi 本身的地址: pi = vector; pi += 3; 指针指向了自己,这样没什么用,但是说明了在做指针算术运算时要小心。访问超出数组范围的内存很危险,应该避免。没有什么能保证被访问的内存是有效变量, 存取无效或无用地址的情况很容易发生。 下面的代码演示了short 和char 类型指针的加法操作: short s; short *ps = &s; char c; char *pc = &c; 我们假设内存分配如图1-8 所示,这里用到的地址以4 字节为界。真实的地址可能涉及不同的字节数和不同的字节序。 图1-8:short 和char 指针 下面的代码给每个指针加1 然后显示内容: printf("Content of ps before: %dn",ps); ps = ps + 1; printf("Content of ps after: %dn",ps); printf("Content of pc before: %dn",pc); pc = pc + 1; printf("Content of pc after: %dn",pc); 运行后,你应该能得到类似如下的结果: Content of ps before: 120 Content of ps after: 122 Content of pc before: 128 Address of pc after: 129 ps 指针增加了2,因为short 的长度是2 字节。pc 指针增加了1,因为它的数据类型长1 字节。这些地址可能没有包含有用的信息。 2. void指针和加法 作为扩展,大部分编译器都允许给void 指针做算术运算,这里我们假设void 指针的长度是4。不过,试图给void 指针加1 可能导致语法错误。在下面的代码片段中,我们声明指针并试图给它加1: int num = 5; void *pv = &num; printf("%pn",pv); pv = pv+1; // 语法警告 下面是警告信息: warning: pointer of type 'void *' used in arithmetic [-Wpointerarith] 这不是标准C 允许的行为,所以编译器发出了警告。不过,pv 包含的地址增加了4 字节。 3. 从指针减去整数 就像整数可以和指针相加一样,也能从指针减去整数。减去整数时,地址值会减去数据类型的长度和整数值的乘积。为了演示从指针减去整数的效果,我们使用如下所示的数组。这些变量的内存分配如图1-7 所示。 int vector[] = {28, 41, 7}; int *pi = vector + 2; // pi: 108 printf("%dn",*pi); // 显示7 pi--; // pi: 104 printf("%dn",*pi); // 显示41 pi--; // pi: 100 printf("%dn",*pi); // 显示28 pi 每次减1,地址都会减4。 4. 指针相减 一个指针减去另一个指针会得到两个地址的差值。这个差值通常没什么用,但可以判断数组中的元素顺序。 指针之间的差值是它们之间相差的“单位”数,差的符号取决于操作数的顺序。这和指针加法是一样的,加到指针上的是数据的长度。我们把“单位”当做操作数。在下例中,我们声明一个数组和数组元素的指针,然后相减: int vector[] = {28, 41, 7}; int *p0 = vector; int *p1 = vector+1; int *p2 = vector+2; printf("p2-p0: %dn",p2-p0); // p2-p0: 2 printf("p2-p1: %dn",p2-p1); // p2-p1: 1 printf("p0-p1: %dn",p0-p1); // p0-p1: -1 在第一个printf 语句中,我们看到数组的最后一个和第一个元素的位置相差2, 就是说它们的索引值相差2。在最后一个printf 语句中,差值是-1,表示p0 在p1 前面,而且它们紧挨着。图1-9 说明了本例中内存的分配情况。 图1-9:指针相减 ptrdiff_t 类型表示两个指针差值的可移植方式。在上例中,指针相减的结果以ptrdiff_t 类型返回。因为指针长度可能不同,这个类型简化了处理差值的任务。 不要把这种技术和利用解引操作来做数字相减混淆。在下例中,我们用指针来确定数字中第一个元素和第二个元素中存储的值的差。 printf("*p0-*p1: %dn",*p0-*p1); // *p0-*p1: -13 1.3.2  比较指针 指针可以用标准的比较操作符来比较。通常,比较指针没什么用。然而,当把指针和数组元素相比时,比较结果可以用来判断数组元素的相对顺序。 我们仍然用前面“指针相减”中使用的vector 数组来说明指针的比较。这里用到了几种比较操作符,结果为1 表示真,为0 表示假: int vector[] = {28, 41, 7}; int *p0 = vector; int *p1 = vector+1; int *p2 = vector+2; printf("p2>p0: %dn",p2>p0); // p2>p0: 1 printf("p2<p0: %dn",p2<p0); // p2<p0: 0 printf("p0>p1: %dn",p0>p1); // p0>p1: 0

展开全文

推荐文章

猜你喜欢

附近的人在看

推荐阅读

拓展阅读

《深入理解C指针》其他试读目录

• 1.1  指针和内存
• 1.2  指针的长度和类型
• 1.3  指针操作符 [当前]
• 1.4  指针的常见用法
• 1.5  小结