C 语言中的指针运算
C 语言中的指针变量存储另一个变量的地址。该地址始终为整数。那么,我们可以对指针执行加法和减法等算术运算吗?在本章中,我们将解释哪些算术运算符使用指针作为操作数,以及哪些运算没有被定义为使用指针执行。
C 语言指针算术运算与一般的算术运算不同。以下是 C 语言中一些重要的指针算术运算:
- 指针的递增和递减
- 指针对整数的加减
- 指针的减法
- 指针的比较
让我们借助示例详细讨论所有这些指针算术运算。
指针的递增和递减
我们知道,在 C 语言中,"++"和"--"分别用作递增和递减运算符。它们是一元运算符,以前缀或后缀方式与数值型变量操作数一起使用,它们将变量的值加一或减一。
假设在内存地址 1000 处创建一个整型变量"x",其值为 10。然后,执行"x++"操作将"x"的值改为 11。
int x = 10; // 在地址 1000 处创建 x++; // x 变为 11
如果我们将"y"声明为指向"x"的指针,并将"y"加1(使用"y++")会发生什么?假设"y"本身的地址是2000。
int x = 10; // 在地址1000处创建 // "y"在地址2000处创建 // 它保存的是1000("x"的地址) int *y = &x; y++; // y 变为 1004
由于变量"y"存储的是 1000("x"的地址),我们预期它会因为"++"运算符而变为 1001,但它却增加了 4,也就是"int"变量的大小。
这是因为,如果"x"的地址是 1000,那么它占用 4 个字节:1000、1001、1002 和 1003。因此,下一个整数只能放在 1004 中,而不能放在它之前。因此,"y"(指向"x"的指针)在增加后变为 1004。
指针增加示例
以下示例展示了如何增加指针 -
#include <stdio.h> int main(){ int x = 10; int *y = &x; printf("Value of y before increment: %d ", y); y++; printf("Value of y after increment: %d", y); }
输出
运行代码并检查其输出 −
Value of y before increment: 6422036 Value of y after increment: 6422040
您可以看到值增加了 4。同样,"--"运算符将值按数据类型的大小递减。
指针递减示例
让我们将"x"和"y"的类型更改为"double"和"float",并查看递减运算符的效果。
#include <stdio.h> int main(){ double x = 10; double *y = &x; printf("value of y before decrement: %ld ", y); y--; printf("value of y after decrement: %ld", y); }
输出
Value of y before decrement: 6422032 Value of y after decrement: 6422024
声明数组时,元素存储在相邻的内存位置。对于"int"数组,每个数组下标相隔 4 个字节,如下图所示 -

因此,如果一个变量存储的是数组第 0 个元素的地址,则"increment"操作会将其移至第 1 个元素。
通过递增指针遍历数组的示例
以下示例展示了如何通过连续递增指针来遍历数组 -
#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 ", 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
指针与整数的加减运算
指针可以与整数相加或相减。当将整数与指针相加时,指针指向下一个内存地址。类似地,当从指针中减去一个整数时,指针指向先前的内存位置。
对指针进行整数加减运算不会将整数值加到指针上或减去指针上的值,而是将整数值乘以数据类型的大小。
例如,有一个整数指针变量 ptr,它指向地址 123400,如果将 ptr 加 1(ptr+1),它将指向地址 123404(整数的大小为 4)。
我们来计算一下:
ptr = 123400 ptr = ptr + 1 ptr = ptr + sizeof(int)*1 ptr = 123400 + 4 ptr = 123404
向指针添加值的示例指针
在下面的例子中,我们声明了一个数组和指向数组的指针。使用数组的第一个元素初始化指针,然后将一个整数值 (2) 添加到指针以获取数组的第三个元素。
#include <stdio.h> int main() { int int_arr[] = {12, 23, 45, 67, 89}; int *ptrArr = int_arr; printf("Value at ptrArr: %d ", *ptrArr); //在 ptrArr 中添加 2 ptrArr = ptrArr + 2; printf("Value at ptrArr after adding 2: %d ", *ptrArr); return 0; }
输出
Value at ptrArr: 12 Value at ptrArr after adding 2: 45
指针减法示例
在以下示例中,我们声明了一个数组和一个指向该数组的指针。首先用数组的最后一个元素初始化指针,然后从指针中减去一个整数值 (2) 以获取数组的第三个元素。
#include <stdio.h> int main() { int int_arr[] = {12, 23, 45, 67, 89}; int *ptrArr = &int_arr[4]; // 指向最后一个元素 printf("Value at ptrArr: %d ", *ptrArr); // 将 ptrArr 减 2 ptrArr = ptrArr - 2; printf("Value at ptrArr after adding 2: %d ", *ptrArr); return 0; }
输出
Value at ptrArr: 89 Value at ptrArr after adding 2: 45
指针减法
我们熟悉"+"和"-"运算符,它们用于常规数字操作数。然而,当将这些运算符用于指针时,它们的行为略有不同。
由于指针是相当大的整数(尤其是在现代 64 位系统中),因此两个指针的加法毫无意义。当我们将 1 加到指针上时,它指向下一个可能存储整数的位置。显然,当我们将一个指针(本身就是一个大整数)相加时,它指向的位置可能不在内存布局中。
但是,两个指针的减法是现实可行的。它返回可容纳两个指针的数据类型的数量。
两个指针相减的示例
我们以上面示例中的数组为例,对 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]; // 第零个元素 int *y = &a[9]; // 最后一个元素 printf("Add of a[0]: %ld add of a[9]: %ld ", 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 个整数。
指针比较
可以使用关系运算符(例如"=="、"<"和">")来比较指针。如果"p1"和"p2"指向彼此相关的变量(例如同一数组的元素),则可以对"p1"和"p2"进行有意义的比较。
比较指针的示例
在下面的示例中,我们声明两个指针,并分别用数组的第一个和最后一个元素初始化它们。只要第一个变量指针指向的地址小于或等于数组最后一个元素的地址,即"&var[MAX 1]"(即第二个指针),我们就会不断增加第一个变量指针。
#include <stdio.h> const int MAX = 3; int main() { int var[] = {10, 100, 200}; int i, *ptr1, *ptr2; // 初始化指针 ptr1 = var; ptr2 = &var[MAX - 1]; while (ptr1 <= ptr2) { printf("Address of var[%d] = %p ", i, ptr1); printf("Value of var[%d] = %d ", i, *ptr1); /* 指向前一个位置 */ 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