当定义了int a[3]后,int* b = a和int (*c)[3] = &a有什么区别吗?

问题描述 投票:0回答:1

我想加深对C语言中指针相关语法的理解,我注意到,如果我先创建一个int的数组。int(*)[] 是给这个数组一个指针的方法,似乎也可以通过简单的使用 int *. 所以我很困惑,下面代码中指针b和指针c有什么区别?如果它们是不同的,那么我应该在什么时候使用一种方式而不是选择另一种方式?

#include <stdio.h>

int main(void)
{
    int a[3];    
    int* b = a;
    int (*c)[3] = &a;

    printf("%p\n", a);
    printf("%p\n", b); 
    printf("%p\n", c); //these 3 outputs are same.
} 

我只是试着加了几行代码来进一步理解这个问题。

    a[2] = 3;

    printf("%i\n", a[2]); // = 3
    printf("%i\n", b[2]); // = 3

看起来b和c是不同的,因为 printf("%i\n", c[2]) 会产生一个错误。如何解释和理解以上这些?

c pointers
1个回答
1
投票

既是 bc 指向同一个内存,但差别很大。

  1. 这是两种不同的类型(指针指向) int 和指向3个数组的指针 ints)
  2. b 解引到一个由 bc 被派生为3个数组。ints,这意味着你可以给一个整数。*b (*b = 10;),但你却不能用同样的方式来处理 c (但只限于指定的索引 (*c)[0] = 10)
  3. 指针算术也是不同的 b + 1 将增加价值的 bsizeof(int)c + 1 将增加价值的 c3*sizeof(int)

如果它们是不同的,我什么时候应该使用一种方式而不是选择另一种?

和C语言中的其他类型一样,应该根据你的需求和应用来使用。最常用的是 int *b; 选项,因为它给了你更多的灵活性。有了这样的指针,你可以处理任何大小的数组,它更常用,也更易读。而指向数组的指针可以将你绑定到一个预先定义好的大小的数组上,它的语法可读性较差(在我看来),因此将更难审查和调试代码。在我的经验中,我从来没有见过使用指针到数组的生产代码,但这并不意味着你不能使用它,如果你发现它在你的应用程序中的任何优势。


1
投票

所以我很困惑,下面代码中的指针b和指针c有什么区别?

它们的类型。b 的类型是 int *c 属于 int (*)[3].

数组的地址和数组中第一个元素的地址是一样的,所以它们指向的内存位置在这里会是一样的,但是按照它们的类型,对它们进行操作,比如指针运算,会产生完全不同的结果。


0
投票

我们先来直观的表示一下。

           int [3]    int *     int (*)[3]
           -------    -----     ----------
   +---+
   |   |   a[0]       b[0]      c[0]
   + - +
   |   |   a[1]       b[1]
   + - +
   | 3 |   a[2]       b[2]
   +---+
   |   |                        c[1]
   + - +
   |   |
   + - +
   |   |
   +---+
   |   |                        c[2]
   + - +
   |   |
   + - +
   |   |
   +---+

最左边的是内存的视图,它是一个3元素数组的序列。int 其余各栏显示了每一栏的情况。a[i], b[i]c[i] 的解释。

由于 a 被宣布为 int [3]b 被宣布为 int *,每个 a[i]b[i] 有型 int (a[i] == *(a + i)).

但是 c 是不同的--因为 c 被声明为"指针 到3元素阵列 int" (int (*)[3]),那么每个 c[i] 有类型"三元素阵列 int" (int [3]). 所以,与其说是第三要素的 a, c[2]第一 的元素 第三次 下面的3元素阵列 a.

© www.soinside.com 2019 - 2024. All rights reserved.