C语言中数组指针关于p=a,p=&a等问题!!

2024-11-06 03:39:29
推荐回答(5个)
回答(1):

问题1:一维数组名与二维数组名含义是不一样的,当然跟你理解的指向行或者列是有一定的偏差的。
对于一维数组,比如int a[4],a代表的是int型的指针,其地址指向a[0],对于二维数组比如a[2][4],a代表的是也是指针,只不过不是简单的int型指针,而是你代码中的数组指针,它与一维数组中指针的区别是:当一维数组名a++时(即步长),指针移动字节数为int型数据所占字节数,但是对于二维数组中a++时,指针移动字节数为列数乘以int型数据所占字节数,即4(代表数组有4列)乘以sizeof(int)。

问题2:先说一下&a代表的意思。假设数组为int a[4]
对于一维数组&a代表的是int型数组指针,它与a的区别是a是int型指针,但是&a代表是int型数组指针,&a的步长为以为数组大小乘以int型数据所占字节数,所以当p = a时,这两个类型不匹配,因为p为int型数组指针,a为简单int型指针,对于表达式p = &a,这个表达式刚好类型匹配,它们的步长都是(4 * sizeof(int))。

问题3:对于int (*p)[4]代表的是int型数组指针,步长是(4 * sizeof(int))。首先说明的是对于第7行程序打印的结果不是a[3]对应的值,这样的操作属于越界(即访问到数组外的内存)。对于(*p)[3]表达式代表*(p + 3),因为p步长为16字节(假设int型数据占4字节),所以*(p + 3)其实访问的是数组首地址加上16乘以3地址处的数据。

问题4:对于二维数组int a[2][4]以及int (*p)[4],因为a与p都是int型数组指针,所以类型匹配,所以对于第6行:p = a即可,如果想输出a[0][3],用printf("%d\n", *(*(p) + 3));即可。对于二维数组而言,存在&a的语句,它同样是数组指针,其步长是行数乘以列数乘以int型所占字节数,对于
int a[2][4],&a的步长为2 * 4 * sizeof(int)。

问题:对于二维数组*score它也是一个指针,并且是个数组指针,如果改成&score以后,虽然都是数组指针,但是步长不一致,编译器会报警告。

希望上述回答对你有一定帮助。

回答(2):

你必须明白,任何指针的值是一个地址这很简单,但指针还承载着很多其他信息,不然就没有int *、char *、double *……之分了。若有int a[4]={1,2,3,4},*p,(*q)[4];则p=a和q=&a虽然都使p和q指向了同一个地址,但二者承载的其他信息不同:前者是使p指向a[0],并使p+1指向a[1]……依次类推,p+3指向a[3];而后者是使q指向数组a的首地址,当然其值与a[0]的地址相同,但承载的其他信息是q+1指向下一行,因为这里没有下一行,它就指向了a[4]的地址(当然这里没有定义a[4],实际是跳出数组了)。你可以这样试试——
void main(void){
int a[4]={1,2,3,4},*p,(*q)[4];
p=a;
q=&a;
printf("p=%p p+1=%p\nq=%p q+1=%p\n",p,p+1,q,q+1);
}
关于(*p)[3]表示7的问题:你已使p=&a,那么*p就等于a(*p是取p中的内容,请不要与声明时的*p相混淆,尽管它们写法一样),再取a的第3个元素是7自然正确。就是说printf("%d\n",(*p)[3]);中的(*p)[3]被编译器解释成为“取指针p的内容,再取以这个内容为首地址的数组的第3个元素”,结果与a[3]等效。

回答(3):

问题1:你这种理解是对的;比如数组int b[2][2]={1,2,3,4};对于int *p=b[0];那么p指向的数据就是{1,2};同理,*p=b[1];p指向{3,4};
问题2:在32位系统中,确实a 和 &a传递的值都是数组的首地址(4BYTES);但是有个传递给什么类型数据的问题,如果是传递给简单的指针如int *p;那么这两种形式没有差别;汇编代码完全是一样的;但是你这里是传递给指针数组int (*p)[4];就有类型匹配的问题在里面;这时的p表示的是指针数组的首地址,而不是一个简单的变量你要明白;
问题3:依然是行指;(*p)[3]表示的是数组的第4个元素要注意;
问题4:二维以上数组的数组名是没有任何意义的;比如二维;a[2][4];有意义的首地址是a[0]和a[1];
程序2:明确地告诉你:不能!
注意score是二维数组;二维数组的数组名称不能像一维那样代表首地址;如果非得取首地址;那么是如下的取法:(加*)
int a[2][2]={1,2,3,4};
00401028 C7 45 F0 01 00 00 00 mov dword ptr [ebp-10h],1
0040102F C7 45 F4 02 00 00 00 mov dword ptr [ebp-0Ch],2
00401036 C7 45 F8 03 00 00 00 mov dword ptr [ebp-8],3
0040103D C7 45 FC 04 00 00 00 mov dword ptr [ebp-4],4
18: int *p=*a;
00401044 8D 45 F0 lea eax,[ebp-10h]//第一个数据的地址传递给eax
00401047 89 45 EC mov dword ptr [ebp-14h],eax//eax传递给参数*p

回答(4):

先跟你说最后的问题吧。其他的你百度hi我,或者其他方式解答。

a[n],*[a+n]等价能理解吧?所以a是一个指针,代表数组的首地址,指向一个数组类型(如int float)的变量。

那么b[N][M],可以试着这样理解:把b[N]看作a,那么b[n][m]与*(b[n]+m)等价。由于a是一个指针,

所以b[N]代表的,是一个指针数组。b所代表的,是指向一个指针数组的指针,并且是b[N]的首地址。

average第一个参数需要的是一个float指针,所以赋值*score 即 score[N]指针数组的首个指针,代表&score[0][0]。

可以改写成&score[0][0],但不能写成&score。

回答(5):

根据数组下标记最好,比如说你定义一个a[5]={2,3,5,6,7},那么a[0]=2,a[1]=3,a[2]=5......
在一个变量前加一个*表示是一个指针变量,他是指向变量地址的指针的,所以要加一个&表示取地址;
这个还是那句话,你只管下标,
int (*p)[2][4];//也要改二维的
p=&a;
printf("%d\n",(*p)[0][3]);
&这个表示取地址,而12是个常量 这样就不能用&,而*score表示一个指针变量