3

我们刚刚开始研究我的 C/C++ 类中的指针,我对它们的工作方式有点困惑。我遇到了这个问题:

假设您已经声明了一个多维数组 char ma[5][30]。元素“ma[0][0]”的地址是什么?使用两 (2) 种不同的方式将地址分配给指针变量 p。(不要给出 ma[0][0] 的具体地址 - 根据分配的内存,每次运行程序时都会有所不同。)

我知道这个社区对提供家庭作业问题的“答案”有多么不满。我不需要答案,但希望有人可以向我解释如何使用指针来获取数组中元素的地址?

4

6 回答 6

4

这两种方法是

char* p1 = (char*)ma;
char* p2 = &ma[0][0];

第一个有效,因为“ma”已经是指向存储数组的内存位置的指针。

第二个使用地址运算符 (&) 工作。&ma[0][0] 翻译为“ma 的地址,元素 0,0”

于 2013-09-17T20:38:17.703 回答
3

假设你有一个指针 p; 使用 & 运算符获取内存。

p = &ma[row][col];

或者您可以从数组的变量名中获得一个指针。

p = ma;

然后你使用指针算法来访问它。

p = p + (row * num_per_col + col);
于 2013-09-17T20:35:46.887 回答
1

There are actually three straightforward ways to obtain a pointer to the element at index (0,0), two of which are cast-free:

char const* const p1 = (char const*)ma;
char const* const p2 = ma[0];
char const* const p3 = &ma[0][0];

The reason why these work is due to the memory layout of ma. Your matrix is just a series of 150 consecutive chars (i.e. 150 bytes). C allows us to decay arrays to pointers to their respective first element whenever we wish to. In fact, this mechanism is so promiscuous, that people are sometimes led to believe there to be no difference between an array and a pointer.

Let's start with the second line (p2). ma[0] is a one-dimensional array of 30 elements of type char and C allows us to have that expression decay into a pointer, pointing at the very first element in the 30 char array. The third line (p3), explicitly fetches the address of element [0][0]. To use this, we don't even have to understand how the memory is laid out.

The first line (p1) is a bit nasty, because it involves a cast. Normally, we could have ma decay to a pointer to a char array, since the first element of ma is an array, not a char. But we know that the very first element of that array is the char we are looking for, so we rely on the array to have no padding before the first element and reinterpret the address of the entire first array as the address of its first char.

于 2013-09-17T21:07:01.087 回答
0

你可以得到它像

&ma[0][0];

如果您将多维数组定义为int [][],则x = y[a][b]相当于x = *((int *)y + a * NUMBER_OF_COLUMNS + b);参考答案)

于 2013-09-17T20:37:18.323 回答
0

除非它是sizeof或一元运算符的操作数&,或者是用于在声明中初始化另一个数组的字符串文字,否则“N 元素数组T”类型的表达式将被转换(“衰减”)为键入“pointer to T”,表达式的值将是数组第一个元素的地址。

假设声明

char ma[5][30];

那么以下所有情况都是正确的:

  1. 表达式ma的类型为“5 元素数组中的 30 元素数组char”。除非masizeofor 或 unary的操作数&,否则它将被转换为类型为“指向 30 元素数组的指针char”或的表达式char (*)[30],其值将是数组中第一个元素的地址,或&ma[0]

  2. 该表达式ma[i]的类型为“30 元素数组char”。除非ma[i]sizeofor 或 unary的操作数&,否则它将被转换为类型为“指针char”或的表达式char *,其值将是数组中第一个元素的地址,或&ma[i][0]

  3. 表达式ma[i][j]具有类型char

  4. 该表达式&ma的类型为“指向 30 元素数组的 5 元素数组的指针char,或char (*)[5][30].

  5. 表达式&ma[i]具有类型char (*)[30]

  6. 表达式&ma[i][j]具有类型char *

  7. 表达式, , , , 和的都相同;数组的地址与数组的第一个元素的地址相同。 ma&mama[0]&ma[0]&ma[0][0]

请注意,类型char (*)[30]char (*)[5][30]兼容char *或者彼此不兼容;如果要将这些类型的值分配给 type 的变量char *,则需要使用显式强制转换,例如char *p = (char *) ma;.

编辑

类型很重要;指针算术基于指向的类型,因此类似的表达式ptr+1将根据指向的类型给出不同的结果ptr。例如:

#include <stdio.h>

int main( void )
{
  char ma[5][30] = {{0}};

  char (*p0)[5][30] = &ma;
  char (*p1)[30]    = &ma[0];
  char *p2          = &ma[0][0];

  printf("%5s%-15s%-15s\n"," ","ptr","ptr+1");
  printf("%5s%-15s%-15s\n"," ","-----","-----");
  printf("%-5s%-15p%-15p\n","p0", (void *) p0, (void *) (p0+1));
  printf("%-5s%-15p%-15p\n","p1", (void *) p1, (void *) (p1+1));
  printf("%-5s%-15p%-15p\n","p2", (void *) p2, (void *) (p2+1));

  return 0;
}

我创建了三个不同类型的指针;p0is of typechar (*)[5][30]并获取 的结果&map1is of typechar (*)[30]并获取 的结果&ma[0]p2is of typechar *并获取 的结果&ma[0][0]。然后我打印每个指针的值,而不是每个指针的值加 1。结果如下:

     指针指针+1
     ----- -----
p0 0x7fff36670d30 0x7fff36670dc6
p1 0x7fff36670d30 0x7fff36670d4e
p2 0x7fff36670d30 0x7fff36670d31

每个指针都以相同的值开始,但在指针上加 1 会根据类型给出不同的结果。 p0指向 的 5x30 元素数组char,因此p0 + 1将指向 的下一个 5x30 元素数组的开头charp1指向 的 30 元素数组char,因此p1 + 1指向char( ma[1]) 的下一个 30 元素数组。最后,p2指向单个char,所以p2 + 1指向下一个字符 ( ma[0][1])。

于 2013-09-17T22:18:58.427 回答
-2

或者您从数组中获取 (x,y) 处的值addr = &ma[0][0] + sizeof(<type of array>)*columns * x + sizeof(<type of array>) * y

于 2013-09-17T20:39:20.040 回答