如何使用指针引用数组中元素的地址?

时间:2013-09-17 20:34:47

标签: c++ c arrays pointers

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

  

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

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

6 个答案:

答案 0 :(得分:4)

两种方式是

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

第一个起作用是因为“ma”已经是指向存储阵列的内存中某个位置的指针。

第二个使用address-of运算符(&)。 & ma [0] [0]转换为“ma的地址,元素0,0”

答案 1 :(得分:3)

假设你有一个指针p;用&amp ;,抓住记忆。操作

p = &ma[row][col];

或者你可以有一个来自数组变量名的指针。

p = ma;

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

p = p + (row * num_per_col + col);

答案 2 :(得分:1)

实际上有三种直接的方法可以获得指向索引(0,0)的元素的指针,其中两个是无投射的:

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

这些工作的原因是ma的内存布局。你的矩阵只是一系列150个连续的字符(即150个字节)。 C允许我们在需要时将数组衰减到指向各自第一个元素的指针。事实上,这种机制是如此混杂,人们有时会相信数组和指针之间没有区别。

让我们从第二行(p2)开始。 ma[0]是一个包含30个char类型元素的一维数组,C允许我们将该表达式衰减为指针,指向30个char数组中的第一个元素。第三行(p3)显式获取元素[0][0]的地址。要使用它,我们甚至不必了解内存是如何布局的。

第一行(p1)有点讨厌,因为它涉及演员。通常,我们可能会ma衰减到指向char数组的指针,因为ma的第一个元素是数组,而不是char。但是我们知道该数组的第一个元素是我们正在寻找的char,所以我们依赖于数组在第一个元素之前没有填充,并将整个第一个数组的地址重新解释为它的第一个char的地址。

答案 3 :(得分:0)

你可以像

那样得到它
&ma[0][0];

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

答案 4 :(得分:0)

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

假设声明

char ma[5][30];

然后以下所有情况都是正确的:

  1. 表达式ma的类型为“{-1}}的30个元素数组的5个元素数组”。除非charma或一元sizeof的操作数,否则它将转换为“指向30个元素数组&”的类型的表达式,或{ {1}},其值将是数组中第一个元素的地址,或char

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

  3. 表达式char *的类型为&ma[i][0]

  4. 表达式ma[i][j]的类型为“指向{-1}}或char的30元素数组的5元素数组的指针。

  5. 表达式&ma的类型为char

  6. 表达式char (*)[5][30]的类型为&ma[i]

  7. 表达式char (*)[30]&ma[i][j]char *ma&ma都是相同;数组的地址与数组的第一个元素的地址相同。

  8. 请注意,ma[0]&ma[0]类型与&ma[0][0]不是兼容,或彼此相对;如果要将这些类型的值分配给类型为char (*)[30]的变量,则需要使用显式强制转换,例如char (*)[5][30]

    修改

    类型重要;指针算法基于指向类型,因此像char *这样的表达式将根据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; } p0的类型为char (*)[5][30],结果为&ma,{ {1}}的类型为p1,其结果为char (*)[30]。然后我打印每个指针的值,而不是每个指针的值加1.以下是结果:

         ptr            ptr+1
         -----          -----
    p0   0x7fff36670d30 0x7fff36670dc6
    p1   0x7fff36670d30 0x7fff36670d4e
    p2   0x7fff36670d30 0x7fff36670d31
    

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

答案 5 :(得分:-2)

或者您从addr = &ma[0][0] + sizeof(<type of array>)*columns * x + sizeof(<type of array>) * y

的数组中得到(x,y)处的值