C

C 知识量:16 - 74 - 317

10.5 指针操作><

指针的操作- 10.5.1 -

C语言对于指针提供了9种不同的基本操作方法:

  1. 赋值:可以把地址赋给指针。例如,用数组名、带地址运算符(&)的变量名、另一个指针进行赋值。

  2. 解引用:*运算符给出指针指向地址上储存的值。

  3. 取址:和所有变量一样,指针变量也有自己的地址和值。对指针而言,&运算符给出指针本身的地址。

  4. 递增指针:递增指向数组元素的指针可以让该指针移动至数组的下一个元素。

  5. 递减指针:递减指向数组元素的指针可以让该指针移动至数组的上一个元素。

  6. 指针与整数相加:可以使用+运算符把指针与整数相加,或整数与指针相加。无论哪种情况,整数都会和指针所指向类型的大小(以字节为单位)相乘,然后把结果与初始地址相加。

  7. 指针减去一个整数:可以使用-运算符从一个指针中减去一个整数。指针必须是第1个运算对象,整数是第2个运算对象。该整数将乘以指针指向类型的大小(以字节为单位),然后用初始地址减去乘积。

  8. 指针求差:可以计算两个指针的差值。通常,求差的两个指针分别指向同一个数组的不同元素,通过计算求出两元素之间的距离。差值的单位与数组类型的单位相同。

  9. 比较:使用关系运算符可以比较两个指针的值,前提是两个指针都指向相同类型的对象。

下面是一个指针操作的示例:

#include <stdio.h>

int main(void) {
    int number[5] = {100, 200, 300, 400, 500};
    int * ptr1, *ptr2, *ptr3;
    
    ptr1 = number; // 把一个地址赋值给指针ptr1    
    ptr2 = &number[2]; // 把一个地址赋值给指针ptr2                           
    
    // 解引用指针,以及获得指针的地址   
    printf("pointer value, dereferenced pointer, pointer address:\n");
    printf("ptr1 = %p, *ptr1 =%d, &ptr1 = %p\n", ptr1, *ptr1, &ptr1);
    printf("ptr2 = %p, *ptr2 =%d, &ptr2 = %p\n", ptr2, *ptr2, &ptr2);
    
    // 指针与整数相加   
    ptr3 = ptr1 + 4;
    printf("\nadding an int to a pointer:\n");
    printf("ptr1 + 4 = %p, *(ptr1 + 4) = %d\n", ptr1 + 4, *(ptr1 + 4));
    
    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 = %td\n", ptr2, ptr1, ptr2 - ptr1);
    
    // 一个指针减去一个整数    
    printf("\nsubtracting an int from a pointer:\n");
    printf("ptr3 = %p, ptr3 - 2 = %p\n", ptr3, ptr3 - 2);
    system("pause");
    return 0;
}

运行结果为:

pointer value, dereferenced pointer, pointer address:
ptr1 = 0061ff18, *ptr1 =100, &ptr1 = 0061ff14
ptr2 = 0061ff20, *ptr2 =300, &ptr2 = 0061ff10

adding an int to a pointer:
ptr1 + 4 = 0061ff28, *(ptr1 + 4) = 500

values after ptr1++:
ptr1 = 0061ff1c, *ptr1 = 200, &ptr1 = 0061ff14

values after --ptr2:
ptr2 = 0061ff1c, *ptr2 = 200, &ptr2 = 0061ff10

Pointers reset to original values:
ptr1 = 0061ff18, ptr2 = 0061ff20

subtracting one pointer from another:
ptr2 = 0061ff20, ptr1 = 0061ff18, ptr2 - ptr1 = 2

subtracting an int from a pointer:
ptr3 = 0061ff28, ptr3 - 2 = 0061ff20

以上代码中,用于显示两个指针相减结果的printf()函数转换说明为%td。

需要注意的是:编译器不会检查指针是否仍指向数组元素,即当移动指针时,需要自己确保指针没有超出数组元素范围。

解引用未初始化的指针- 10.5.2 -

需要格外注意的是:千万不要解引用未初始化的指针。例如:以下代码是错误的。

int * p;  //未初始化的指针p
*p = 100; //错误的解引用

因为指针p没有初始化,其存储的地址是随机的,将值100赋给*p后,将不会知道值100到底存储到了哪里。这可能不会出什么错,也可能会擦写数据或代码,或者导致程序崩溃。

创建一个指针时,系统只分配储存指针本身的内存,指针内的值(即地址)是随机的。因此,在使用指针之前,必须先用已分配的地址初始化它,使指针指向一个明确的地址。例如:

int n = 100;//创建一个变量n
int * p;    //创建一个未初始化的指针p    
p = & n;    //初始化指针p,使p指向变量n的地址

当程序创建变量n后,会给变量n分配一个内存空间即变量地址,创建指针p后,也会为指针p自身分配一个地址,但是p的值是随机的。将变量n的地址赋给指针p后,指针p的值就将确定为变量n的地址,这样就可以解引用指针p,会得到变量n的值:100。