Cprogramming 简明教程
Pointer Arithmetics in C
C 中的 pointer 变量存储另一个变量的地址。地址始终是整数。那么,我们可以在指针上执行加法和减法等算数运算吗?在本章中,我们将解释哪些算数运算符在 C 中使用指针作为操作数,以及哪些运算没有定义可在指针上执行。
C pointers arithmetic operations 不同于一般的算术运算。以下是在 C 中的一些重要的指针算数运算:
-
指针的增量和减量
-
指针与整数的加减法
-
Subtraction of Pointers
-
Comparison of Pointers
让我们借助示例详细讨论所有这些指针算术运算。
Increment and Decrement of a Pointer
我们知道"++"和"--"用作 increment and decrement operators in C 。它们是一元运算符,以前缀或后缀方式与数字 variable 操作数一起使用,它们将变量的值增加或减少一。
假设在内存中地址为1000处创建了一个整数变量"x",其值为10。那么,"x++"会使"x"的值变为11。
int x = 10; // created at address 1000
x++; // x becomes 11
如果我们声明"y"为"x"的指针,并将"y"按1 (使用"y++")增加,会发生什么?假定"y"本身的地址为2000。
int x = 10; // created at address 1000
// "y" is created at address 2000
// it holds 1000 (address of "x")
int *y = &x ;
y++; // y becomes 1004
由于变量"y"存储1000("x"的地址),因此我们希望因"++"运算符而变为1001,但它却增加了4,这是"int"变量的大小。
之所以出现这种情况,是因为如果"x"的地址为1000,那么它将占据4个字节:1000、1001、1002和1003。因此,下一个整数只能放在1004中,不能放在它之前。因此,当"y"("x"的指针)增加时变为1004。
Example of Incrementing a Pointer
以下示例显示了如何增加一个指针的值 −
#include <stdio.h>
int main(){
int x = 10;
int *y = &x;
printf("Value of y before increment: %d\n", y);
y++;
printf("Value of y after increment: %d", y);
}
运行代码并检查其输出:
Value of y before increment: 6422036
Value of y after increment: 6422040
可以看到,该值增加了4。同样,"--"运算符将值减小数据类型的字节数。
Example of Decrementing a Pointer
让我们将"x"和"y"的类型更改为"double"和"float",看看减号运算符的效果。
#include <stdio.h>
int main(){
double x = 10;
double *y = &x;
printf("value of y before decrement: %ld\n", y);
y--;
printf("value of y after decrement: %ld", y);
}
Value of y before decrement: 6422032
Value of y after decrement: 6422024
声明一个 array 时,元素存储在相邻的内存位置中。在"int"数组的情况下,每个数组下标都相隔4个字节,如下图所示 −
因此,如果一个变量存储数组第0个元素的地址,那么"增量"会将其移至第1个元素。
Example of Traversing an Array by Incrementing Pointer
以下示例显示了如何通过连续增加指针的值来遍历数组 −
#include <stdio.h>
int main(){
int a[]= {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int len = sizeof(a)/sizeof(int);
int *x = a;
int i = 0;
for(i = 0; i < len; i++){
printf("Address of subscript %d = %d Value = %d\n", i, x, *x);
x++;
}
return 0;
}
运行代码并检查其输出:
Address of subscript 0 = 6421984 Value = 10
Address of subscript 1 = 6421988 Value = 20
Address of subscript 2 = 6421992 Value = 30
Address of subscript 3 = 6421996 Value = 40
Address of subscript 4 = 6422000 Value = 50
Address of subscript 5 = 6422004 Value = 60
Address of subscript 6 = 6422008 Value = 70
Address of subscript 7 = 6422012 Value = 80
Address of subscript 8 = 6422016 Value = 90
Address of subscript 9 = 6422020 Value = 100
Addition and Subtraction of Integer to Pointer
可以对指针进行整数加减运算。当将一个整数添加到指针时,指针将指向下一个内存地址。同样,当从指针中减去一个整数时,指针将指向前一个内存位置。
将一个整数加减到指针中不会将该值加减到指针中,而是将与数据类型的大小相乘的值加减到指针中。
例如,有一个整数指针变量ptr,它指向地址123400,如果向ptr添加1 (ptr+1),它将指向地址123404(整数的大小为4)。
让我们计算一下,
ptr = 123400
ptr = ptr + 1
ptr = ptr + sizeof(int)*1
ptr = 123400 + 4
ptr = 123404
Example of Adding Value to a Pointer
在以下示例中,我们正在声明一个数组和 pointer to an array 。使用数组的第一个元素初始化指针,然后向指针中添加一个整数值(2)以获得数组的第三个元素。
#include <stdio.h>
int main() {
int int_arr[] = {12, 23, 45, 67, 89};
int *ptrArr = int_arr;
printf("Value at ptrArr: %d\n", *ptrArr);
// Adding 2 in ptrArr
ptrArr = ptrArr + 2;
printf("Value at ptrArr after adding 2: %d\n", *ptrArr);
return 0;
}
Value at ptrArr: 12
Value at ptrArr after adding 2: 45
Example of Subtracting Value to a Pointer
在以下示例中,我们声明了一个数组和一个指向数组的指针。用数组的最后一个元素初始化指针,然后从指针中减去一个整数值 (2) 以获取数组的第三个元素。
#include <stdio.h>
int main() {
int int_arr[] = {12, 23, 45, 67, 89};
int *ptrArr = &int_arr[4]; // points to last element
printf("Value at ptrArr: %d\n", *ptrArr);
// Subtracting 2 in ptrArr
ptrArr = ptrArr - 2;
printf("Value at ptrArr after adding 2: %d\n", *ptrArr);
return 0;
}
Value at ptrArr: 89
Value at ptrArr after adding 2: 45
Subtraction of Pointers
当 + 和 "−" 运算符与常规数字操作数一起使用时,我们很熟悉它们。但是,当您将这些运算符与指针一起使用时,它们的行为会稍有不同。
由于指针是相当大的整数(尤其是在现代 64 位系统中),因此两个指针的加法是毫无意义的。当我们向指针添加 1,它指向可能存储整数的下一个位置。显然,当我们添加一个指针(本身是一个大整数)时,它指向的位置可能不在内存布局中。
但是,两个指针的减法是切合实际的。它返回可以放入两个指针中的数据类型的数量。
Example of Subtracting Two Pointers
让我们取前面示例中的数组,并对 a[0] 和 a[9] 的指针执行减法
#include <stdio.h>
int main(){
int a[]= {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int *x = &a[0]; // zeroth element
int *y = &a[9]; // last element
printf("Add of a[0]: %ld add of a[9]: %ld\n", x, y);
printf("Subtraction of two pointers: %ld", y-x);
}
运行代码并检查其输出:
Add of a[0]: 140729162482768 add of a[9]: 140729162482804
Subtraction of two pointers: 9
可以看到两个整数之间的数值差为 36;它表明减法为 9,因为它可以在两个指针之间容纳 9 个整数。
Comparison of Pointers
指针可以使用 relational operators (例如 "==", "<" 和 ">") 进行比较。如果 "p1" 和 "p2" 指向彼此相关的变量(例如同一数组的元素),那么可以对 "p1" 和 "p2" 进行有意义的比较。
Example of Comparing Pointers
在以下示例中,我们声明了两个指针,并分别用数组的第一个元素和最后一个元素对它们进行初始化。只要它指向的地址小于或等于最后一个数组元素的地址 &var[MAX − 1] (即第二个指针),我们将继续递增第一个变量指针。
#include <stdio.h>
const int MAX = 3;
int main() {
int var[] = {10, 100, 200};
int i, *ptr1, *ptr2;
// Initializing pointers
ptr1 = var;
ptr2 = &var[MAX - 1];
while (ptr1 <= ptr2) {
printf("Address of var[%d] = %p\n", i, ptr1);
printf("Value of var[%d] = %d\n", i, *ptr1);
/* point to the previous location */
ptr1++;
i++;
}
return 0;
}
运行代码并检查其输出:
Address of var[0] = 0x7ffe7101498c
Value of var[0] = 10
Address of var[1] = 0x7ffe71014990
Value of var[1] = 100
Address of var[2] = 0x7ffe71014994
Value of var[2] = 200