【问题标题】:What's the difference between the types - int * and int *[100] in C?C中的类型 - int * 和 int *[100] 有什么区别?
【发布时间】:2013-12-17 13:42:09
【问题描述】:

有点菜鸟,所以不要在这里杀了我。

以下代码有什么区别?

int *p;         //As i understand, it creates a pointer to an variable of size int.
int *p[100];    //Don't really know what this is.
int (*p)[100];  // I have come to understand that this is a pointer to an array. 

【问题讨论】:

  • 您是在问 C,还是想知道 C++ 的答案?
  • 另见cdecl.org
  • @Sven Marnach,char *(*(**foo[][8])())[]?我们需要更深入
  • @benjymous,我想听听一些关于 C++ 中指针的有趣内容
  • 请不要对这个问题投反对票 虽然这个问题已经回答了好几次,但在这里我们遇到了一些很好的答案。

标签: c pointers


【解决方案1】:
  1. 这是一个指向int的指针

    int *p;
    
    ┌────┐
    │int*│
    └────┘
    

    它应该指向int,像这样:

    ┌────┐
    │int*│
    └─┃──┘
      ▼
    ┌───┐
    │int│
    └───┘
    
  2. 这是一个由 100 个指向 int 的指针组成的数组

    int *p[100];
    

    也就是说,它会给你 100 个指针。

    ┌────┬────┬────┬────┬────┬────┬┄
    │int*│int*│int*│int*│int*│int*│
    └────┴────┴────┴────┴────┴────┴┄
    

    每个指针都应该指向一个int,可能是这样的:

    ┌────┬────┬────┬────┬────┬────┬┄
    │int*│int*│int*│int*│int*│int*│
    └─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴─┃──┴┄
      ▼    ▼    ▼    ▼    ▼    ▼
    ┌───┐┌───┐┌───┐┌───┐┌───┐┌───┐┌┄
    │int││int││int││int││int││int││
    └───┘└───┘└───┘└───┘└───┘└───┘└┄
    

    当然,他们没有理由不能都指向同一个int,或者其他什么。

    如果您想要许多可以轻松使用的指针,您可能需要使用指针数组 迭代。例如,您可以动态分配对象并使每个指针指向不同的对象:

    p[0] = new int(0);
    p[1] = new int(0);
    // ...
    

    也许动态分配ints 不是最好的例子,但我认为重点很清楚。

  3. 这是一个指向包含 100 个 int 的数组的指针

    int (*p)[100];
    

    也就是说,它只给你一个指针:

    ┌───────────┐
    │int(*)[100]│
    └───────────┘
    

    它应该指向一个包含 100 个ints 的数组:

    ┌───────────┐
    │int(*)[100]│
    └─┃─────────┘
      ▼
    ┌───┬───┬───┬───┬───┬───┬┄
    │int│int│int│int│int│int│
    └───┴───┴───┴───┴───┴───┴┄
    

    当您对数组名称使用地址运算符 (&) 时,您将获得指向数组的指针。例如:

    int arr[100] = { /* some initial values */ };
    int (*p)[100] = &arr;
    

    在这里,我获取了arr 数组的地址,它为我提供了指向该数组的指针。如果你想访问数组的一个元素,你必须先取消引用指针:(*p)[3] 将访问元素 3。


旁注:

永远记住 arrays are not pointers。正如我们刚刚看到的,我们可以使用数组的地址来获取指向它的指针,就像 C++ 中的任何其他(非临时)对象一样。数组和指针之间唯一的特殊联系是数组的名称可以隐式转换为指向数组第一个元素的指针。这意味着以下内容是有效的:

int arr[100] = { /* some initial values */ };
int* p = arr;

指针p 将指向arr 中的第一个元素。请注意,p 不是指向数组的指针,而是指向数组元素的指针。

(另请注意,没有数组类型的函数参数。如果您将int p[]之类的内容写为函数参数,则编译器会将其转换为int*。)

【讨论】:

  • 优秀的 ASCII 艺术 :-)
  • @sftrabbit,如果您也告诉我们何时以及如何使用这三个示例,以及数组和指针之间的关系是什么,那就太好了?我见过很多指针,更少的指针数组,没有指向数组的指针……我什至不知道什么时候需要它们。
  • 我也对 ASCII 印象深刻!
  • @kvv:指针是一个,它可以按需产生一个变量。数组是一个,可以根据需要生成变量集合。所以回答你的问题“我什么时候使用指针?”是“每当您需要将变量视为值”。 “我什么时候使用数组?”的答案是“每当您需要将一组变量视为一个值时”。
【解决方案2】:

听起来您可以使用Spiral Rule 的介绍。

从变量开始,从右到左“螺旋”:

              +-------+
              | +--+  |             // So we have:
              | |  |  |                    p    // p     
          int * p  |  |                  * p    // p is a pointer
           ^  ^    |  |              int * p    // p is a pointer to an int
           |  +----+  |
           +----------+

下一个:

              +--------+
              | +--+   |         p       // p
              | |  V   |         p[100]  // p is an array of 100
          int * p[100] |       * p[100]  // p is an array of 100 pointers
           ^  ^    |   |   int * p[100]  // p is an array of 100 pointers to ints
           |  +----+   |
           +-----------+

最后,规则的新部分,先做括号里的任何事情:

                   +-----+            
                   | +-+ |    
                   | ^ | |         ( p)       // p
              int (* p)  [100];    (*p)       // p is a pointer
               ^   ^   | |         (*p)[100]  // p is a pointer to an array of 100
               |   +---+ |     int (*p)[100]  // p is a pointer to an array of 100 ints
               +---------+    

如果您在线/可以使用计算机,使用cdecl.org 站点总是有用的,但能够离线阅读代码也很重要,这条规则可以让您做到这一点。

【讨论】:

  • 这太棒了!我要把这个打印出来。
  • 以前从来不知道。 +1。
【解决方案3】:

有点菜鸟所以不要在这里杀了我

即使对于专家来说,弄清楚类型在 C 中的含义也可能很棘手。不用担心。

以下代码有什么区别?

其他答案都很好,我无意反驳它们。相反,这是另一种思考方式。我们需要定义三件事:

  • 变量是支持三种操作的东西。 fetch 操作接受一个变量并产生它的当前值。 fetch 操作没有符号;您只需使用变量。 store 操作接受一个变量和一个值,并将值存储在变量中。 address 操作接受一个变量并产生一个指针

  • 指针是支持一个操作的东西。 dereference 操作,写成前缀*pointer,接受一个指针并产生一个变量。 (指针支持其他操作,例如算术和索引——这是算术的一种形式——但我们不要去那里。)

  • 数组是支持一个操作的东西。 index 操作接受一个数组和一个整数并产生一个变量。它的语法是后缀:array[index]

好的,现在我们来回答您的问题。声明是什么

int p;

是什么意思?表达式pint 类型的变量。请注意,这是一个变量;你可以把东西存到p。声明是什么

int *p;

是什么意思?表达式*pint 类型的变量。现在我们知道我们可以推断出p 是什么。因为*p 是一个解引用并产生一个变量,所以p 必须是一个指向int 的指针。声明是什么

int *p[100];

是什么意思?这意味着*表达式*p[i]int 类型的变量,前提是i 是从099 的整数值。我们得到了一个变量,但我们可以从指针或数组中得到,所以我们必须弄清楚是哪个。我们查阅运算符优先级表,发现索引运算符比解引用运算符绑定“更紧密”。那就是:

*p[i]

是一样的
*(p[i])

记住,那个东西是int 类型的变量。括号的内容被取消引用以生成int 类型的变量,因此括号的内容必须是一个指向int的指针。因此

p[i]

是一个指向 int 的指针。这怎么可能?这必须是一个指向 int 类型的变量的获取!所以p[i] 是一个指向int 类型指针的变量。由于这是一个索引操作,p 必须是指向int 的指针数组。

现在你做下一个。

int (*p)[100];

是什么意思?

【讨论】:

    【解决方案4】:

    int *p; --> 声明一个指向整数类型的指针。
    int *p[100]; -->声明一个包含 100 个整数类型指针的数组。
    int (*p)[100]; --> 声明一个指向整数类型的指针100 个整数的数组。

    使用cdecl 翻译此类类型。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-12
      • 2012-08-30
      • 2017-02-23
      • 2021-01-05
      • 2012-06-03
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      相关资源
      最近更新 更多