涉及指针和数组的两个声明之间的区别

int *a[3]int (*a)[3]之间有什么区别?

int a[3]int (a)[3]之间没有区别,它们都声明a为3 int的数组。 int *a[3]int (*a)[3]之间存在差异,前者声明了一个指向int的3个指针的数组,而第二个声明了指向3个int的数组的指针。 括号在这里有所不同,因为在C括号中的优先级高于*。

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

 cdecl> explain int*a[3] 

声明一个指向int的指针数组3

 cdecl> explain int (*a) [3] 

声明一个指向int数组3的指针

如果您有任何疑问,使用这个g ++技巧通常很方便:

 #include  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个指向int的数组。
  2. 指向3个int数组的指针。

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

 int *a[3] 

声明一个3 int*的数组。

 int (*a)[3] 

将a声明为指向int的向量的指针。 这与任何其他指针实际上没什么不同,它只是指向一个更复杂的类型。

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

在阅读C类型声明时,此URL上有一篇很好的文章。 作者Eli Bendersky提供了一种阅读声明的简单方法。 您从变量的名称开始,然后沿着发出您走路时遇到的内容的线移动。 基本方法是从变量名开始并向右移动。 我将提供一个简单的概述,但我强烈建议您阅读这篇文章。

  1. 从变量名开始,向右转。
  2. 如果你击中右边的paren )或分号; 然后转回你开始向右走的地方然后向左走。
  3. 如果你遇到一个左paren (当你向右走,那么你遇到了一个函数声明,接下来是它的逗号分隔的参数列表。 注意 :你会在参数列表的末尾遇到一个正确的paren。上面的规则不适用于此权利paren。
  4. 如果遇到左括号,请将其读作“数组”。
  5. 向左走后,当你击中一个左边的paren (然后回到右边的paren,你最后一次右转。跳过那个右边的paren,然后继续重复。
  6. [重复]

因此,将此规则应用于您的特定问题……

在声明中,“ int * a[3]; ”, a是变量名。 所以,它被读取:

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

在声明中,“ int (* a)[3]; ”, a是变量名。 所以,它被读取:

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