涉及指针和数组的两种声明方式的区别

3
< p >"int *a[3]"和"int (*a)[3]"有什么区别?< /p > 答:第一个声明是一个数组,它包含三个指向整数的指针;第二个声明是一个指针,它指向一个包含三个整数的数组。

1
格式说明,因为似乎原帖作者有些困难:您可以用反引号(`)字符将代码嵌入以保留其格式。 - Joel Coehoorn
6个回答

21

int a[3]int (a)[3]没有区别,它们都声明a为一个由3个int组成的数组。 int *a[3]int (*a)[3]是有区别的,前者声明了一个由3个指向int的指针组成的数组,而后者声明了一个指向由3个int组成的数组的指针。在C语言中,括号比*具有更高的优先级,因此这里括号有所不同。


9

或者,您可以使用cdecl,该工具将以英语输出变量声明的含义。

cdecl> explain int*a[3]

声明一个名为a的数组,其大小为3,每个元素都是指向整型变量的指针。

cdecl> explain int (*a) [3]

声明a为指向包含3个整数的数组的指针


7

如果你有任何疑虑,使用这个 g++ 技巧通常非常方便:

#include <iostream>

template < class T > void describe(T& )
{
  // With msvc, use __FUNCSIG__ instead
  std::cout << __PRETTY_FUNCTION__ << std::endl;
}

int main(int argc, char* argv[])
{
  int *a[3];
  describe(a);

  int (*b)[3];
  describe(b);

  return EXIT_SUCCESS;
}

使用g++编译并运行它,您将得到:

void describe(T&) [with T = int*[3]]
void describe(T&) [with T = int (*)[3]]

所以,它们绝对不是相同的!你拥有的是:

  1. 一个指向3个整数指针的数组。
  2. 一个指向3个整数数组的指针。

问题是关于C语言的,而这里使用的是C++。此外,__PRETTY_FUNCTION__是g++的扩展,不是标准。我认为像@FreeMemory建议的使用cdecl会更简单。 - Robert Gamble
使用MSVC,您可以使用__FUNCSIG__提供类似的功能。 - bltxd
上面的输出并没有解释任何内容。它只是与代码相同的语法,但没有 ab 名称。 - Ropez

6

看起来你的星号在格式中丢失了...

int *a[3]

声明了一个包含3个int*的数组。

int (*a)[3]

声明a为指向整数向量的指针。这与任何其他指针并没有太大区别,只是它指向了一个稍微复杂一些的类型。

int foo[3];
int bar[3];
int (*vp)[3];
vp = &foo;
(*vp)[0] = 0;

3
这里有一篇很棒的文章,可以在这个链接中找到,关于阅读C语言类型声明。作者Eli Bendersky提供了一种简单的阅读声明的方法。你从变量名开始,然后沿着这行走,发现什么就念什么。基本方法是从变量名开始向右移动。我会提供一个简单的概述,但我强烈建议你去阅读这篇文章。
  1. 从变量名开始,向右移动。
  2. 如果遇到右括号)或分号;,则返回到最初向右移动的位置,然后向左移动。
  3. 如果在向右移动时遇到左括号(,则遇到一个函数声明,接下来是它逗号分隔的参数列表。注意:在参数列表的末尾会遇到右括号,上述规则不适用于该右括号。
  4. 如果遇到左方括号,则将其读作“数组”。
  5. 向左移动时,当遇到左括号(时,回到你上次向右移动时的右括号处。跨过那个右括号,然后继续重复向右移动。
  6. [重复]

所以,在将此规则应用于您的特定问题时...

在声明“int * a [3];”中,a是变量名。因此,它的阅读方式为:

a是指向整数(int)的指针(*)数组([),有3个元素([3])

而在声明“ int (* a) [3]; ”中,a是变量名。因此,它的阅读方式为:

a是指向三个元素([3])的整数(int)数组([)的指针(*)。


-2

int *a[3] :a是指向3个整数类型指针的数组

int (*a)[3] :a是指向3个整数类型数组的指针


1
你的回答与之前的有什么不同吗? - slfan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接