我们刚刚开始讨论我的C / C ++类中的指针,我对它们的工作方式感到有些困惑。我遇到了这个问题:
假设你已经声明了一个多维数组char [5] [30]。 元素“ma [0] [0]”的地址是什么?使用两(2)种不同的 将地址分配给指针变量的方法,p。 (不要给 ma [0] [0]的具体地址 - 每次程序都会有所不同 根据分配的内存运行。)
我知道这个社区对提供家庭作业问题的“答案”感到沮丧。我不需要答案,但希望有人可以向我解释如何使用指针来获取数组中元素的地址?
答案 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];
然后以下所有情况都是正确的:
表达式ma
的类型为“{-1}}的30个元素数组的5个元素数组”。除非char
是ma
或一元sizeof
的操作数,否则它将转换为“指向30个元素数组&
”的类型的表达式,或{ {1}},其值将是数组中第一个元素的地址,或char
。
表达式char (*)[30]
的类型为“30个元素数组&ma[0]
”。除非ma[i]
是char
或一元ma[i]
的操作数,否则它将转换为“sizeof
”指针或&
类型的表达式,它的值将是数组中第一个元素的地址,或char
。
表达式char *
的类型为&ma[i][0]
。
表达式ma[i][j]
的类型为“指向{-1}}或char
的30元素数组的5元素数组的指针。
表达式&ma
的类型为char
。
表达式char (*)[5][30]
的类型为&ma[i]
。
表达式char (*)[30]
,&ma[i][j]
,char *
,ma
和&ma
的值都是相同;数组的地址与数组的第一个元素的地址相同。
请注意,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
指向char
(p1
)的下一个30个元素数组。最后,char
指向一个p1 + 1
,因此char
指向下一个字符ma[1]
)。
答案 5 :(得分:-2)
或者您从addr = &ma[0][0] + sizeof(<type of array>)*columns * x + sizeof(<type of array>) * y