指向数组c ++的指针

Sam*_*msh 22 c++ arrays pointers

以下代码在做什么?

int g[] = {9,8};
int (*j) = g;
Run Code Online (Sandbox Code Playgroud)

从我的理解,它创建一个指向2个int数组的指针.但是为什么这会起作用:

int x = j[0];
Run Code Online (Sandbox Code Playgroud)

这不起作用:

int x = (*j)[0];
Run Code Online (Sandbox Code Playgroud)

Ben*_*ell 43

在您的示例中,括号是多余的.指针不关心是否涉及数组 - 它只知道它指向一个int

  int g[] = {9,8};
  int (*j) = g;
Run Code Online (Sandbox Code Playgroud)

也可以改写为

  int g[] = {9,8};
  int *j = g;
Run Code Online (Sandbox Code Playgroud)

也可以改写为

  int g[] = {9,8};
  int *j = &g[0];
Run Code Online (Sandbox Code Playgroud)

指向数组的指针看起来像

  int g[] = {9,8};
  int (*j)[2] = &g;

  //Dereference 'j' and access array element zero
  int n = (*j)[0];
Run Code Online (Sandbox Code Playgroud)

这里有一个很好的读指针声明(以及如何理解它们):http://www.codeproject.com/Articles/7042/How-to-interpret-complex-CC-declarations

  • 本文非常有帮助,特别是从右到左的规则,谢谢。 (2认同)
  • @johnbakers是的,绝对有必要指定数组的长度,否则你将没有指向数组的指针,然后除非使用强制转换,否则代码将无法编译。指向数组意味着您在编译时就知道它的长度。由于在 MSVC++ 中省略数组长度而产生的编译器消息为“错误 C2440: '初始化': 无法从 'int (*)[2]' 转换为 'int (*)[]''” (2认同)

bam*_*s53 22

int g[] = {9,8};
Run Code Online (Sandbox Code Playgroud)

这声明了一个int [2]类型的对象,并将其元素初始化为{9,8}

int (*j) = g;
Run Code Online (Sandbox Code Playgroud)

这声明了一个int*类型的对象,并使用指向g的第一个元素的指针对其进行初始化.

第二个声明用g以外的东西初始化j的事实很奇怪.C和C++只是有关于数组的这些奇怪的规则,这就是其中之一.这里,表达式g从一个引用对象g的左值隐式转换为一个指向g int*的第一个元素的rvalue .

这种转换发生在几个地方.事实上它发生在你这样做的时候g[0].数组索引运算符实际上不在数组上,只在指针上工作.所以该语句int x = j[0];有效,因为g[0]碰巧执行了j初始化时完成的隐式转换.

指向数组的指针就像这样声明

int (*k)[2];
Run Code Online (Sandbox Code Playgroud)

而且你对如何使用它是完全正确的

int x = (*k)[0];
Run Code Online (Sandbox Code Playgroud)

(注意"声明跟随使用",即声明类型变量的语法模仿使用该类型变量的语法.)

但是,通常不使用指向数组的指针.围绕数组的特殊规则的全部目的是,您可以使用指向数组元素的指针,就像它是一个数组一样.因此,惯用的C通常并不关心数组和指针是不是一回事,规则阻止你做任何直接对数组有用的东西.(例如,你不能复制像的数组:int g[2] = {1,2}; int h[2]; h = g;)


例子:

void foo(int c[10]); // looks like we're taking an array by value.
// Wrong, the parameter type is 'adjusted' to be int*

int bar[3] = {1,2};
foo(bar); // compile error due to wrong types (int[3] vs. int[10])?
// No, compiles fine but you'll probably get undefined behavior at runtime

// if you want type checking, you can pass arrays by reference (or just use std::array):
void foo2(int (&c)[10]); // paramater type isn't 'adjusted'
foo2(bar); // compiler error, cannot convert int[3] to int (&)[10]

int baz()[10]; // returning an array by value?
// No, return types are prohibited from being an array.

int g[2] = {1,2};
int h[2] = g; // initializing the array? No, initializing an array requires {} syntax
h = g; // copying an array? No, assigning to arrays is prohibited
Run Code Online (Sandbox Code Playgroud)

因为数组与C和C++中的其他类型非常不一致,所以应该避免使用它们.C++具有std::array更高的一致性,您需要在需要静态大小的数组时使用它.如果你需要动态大小的数组,你的第一个选项是std :: vector.

  • +1 用于准确描述数组/指针关系,而不使用单词“decay”。 (2认同)

Luc*_*ore 9

j[0];取消引用指针int,因此其类型为int.

(*j)[0]没有类型.*j取消引用指向a的指针int,因此它返回一个int,并(*j)[0]尝试取消引用int.这就像尝试一样int x = 8; x[0];.

  • 另外,请记住`j [0]`相当于`*(j + 0)`.`(*j)[0]`因此相当于`j [0] [0]`,它相当于`*(*(j + 0)+ 0)`,它的作用是`**j `.无论你怎么看,它都行不通. (3认同)