C语言&的一些思考

1. C语言里&的一般作用


C语言里有了指针的概念后,当我们需要为指针赋值时,常用的有以下两种方式

void main(){
    // 方法一
    char a = 'A';
    char* p = &a;

    // 方法二
    char* q = (char*)malloc(sizeof(char));
}

总而言之,&可以放在一个变量前面,以取得这个变量对应的内存地址。

2. &放在指针前面


现在来考虑一下下列的两种情况

void main(){
    // 情况一,考虑p1, p2, p3, arr, &arr, arr + 1的关系
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

    int* p1 = arr;
    int* p2 = arr + 1;
    int* p3 = &arr;

    // 情况二,考虑&number, q, &q, p5, p4的关系
    int number = 10;
    int* q = &number;    
    int* p5 = &q;
    int** p4 = &q;
}

实际上这两种情况是:

  • 数组指针取&

  • int指针取&
    首先,我们知道arr是长度为10的整数数组的起始地址,所以有*arr == arr[0]; *(arr + n) = a[n]。所以对于情况一,p1 == arr;p2 == p1 + 1(因为是整数指针,指针加一内存地址加4)。上面这几点只是想点出下面的问题,究竟p3、&arr、arr有着什么关系。当我们用C语言开发工具去运行这段代码打印指针的值,会发现这三者相等,意思是他们指向的都是同一个地址。为什么呢?arr是一个指针,我对一个指针使用&他应该会获取这个指针的指针啊。这里需要注意的是,当&操作的对象是一个非数组类型的指针时,我们如愿以偿获取到了这个指针的指针。但是当我们对数组指针使用&,我们实际上是获取的这个数组的指针,上述的情况是我们获取到了arr这个数组对象的指针,那么这个数组对象的指针就是arr的值。所以,p3 == arr == &arr。不止如此,我们通过&arr获取到的指针的步长是这个数组的元素类型的步长 * 数组长度。而arr这个指针的步长只是元素类型的步长。如下所示

    void main(){
      int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 
    
      int* p1 = arr;
      int* p2 = &arr;
    
      printf("&arr + 1 is %p", (&arr + 1));  // 内存地址:arr + 4(整数的步长为4) * 10(数组的长度为10)
      printf("arr + 1 is %p", (arr + 1));  // 内存地址: arr + 4(整数的步长为4)
      // 综上,(&arr + 1) - (arr + 1) == 36
    
      // 此处的第一反应(p2 + 1) == (&arr + 1)。但是注意我们在赋值给p2的时候,指定了p2的类型为整数指针,所以实际上内存地址:p2 + 1(整数指针) == arr + 4
      printf("p2 + 1 is %p", (p2 + 1));
    }

    再来考虑情况二,我们此时不再对数组指针取&,所以p5, p4, &q, q是什么关系呢?实际上,&q此时不在像情况一那样等于q,它返回的是q这个指针的指针。所以p5 == p4。他们都取到了q这个指针的指针。但是,问题又来了,p5是整数指针的指针,p4只是一个整数指针。所以会带来步长的不一致,p5的步长是一个指针的步长,p4的步长是一个整数的步长。指针的步长是4或者8,这个看系统环境而定。

3. 总结


C语言中&的作用是返回一个地址(指针)。但是具体是返回什么样的值、值等于多少还是&操作的对象有所去别的。

  • 对数组指针取&,返回的是数组的首地址,即&arr == arr,只不过指针的步长不一样
  • 对非指针变量取&,返回这个变量的地址
  • 对非数组类型的指针取&,返回这个指针的指针
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务