考虑一下这个程序,
#include <stdio.h>
int main(){
int a[][4] = {2,3,4,5,
43,32,76,3
};
int *p;
int (*q)[4];
p = (int *)a;
q = a;
printf("%u\t%u", (unsigned int)p,(unsigned int)q);
printf("\n%d\t%d",*(++p),*(++q));
return 0;
}
在上面的程序中,我已经定义了两个指针,
1)整数指针
2)指向数组的指针
使用GCC编译器编译时,我遇到了两个疑问,
问题1:
为什么,声明,
printf("\n%d\t%d",*(++p),*(++q));
当我尝试取消引用(++q)
时,会返回一个地址吗?
问题2:
我有什么方法可以使用&#34;指向数组的指针&#34;变量(&#39; q&#39; - 在这个程序中)来访问一行中的连续元素?
编译:GCC;操作系统:Ubuntu
答案 0 :(得分:4)
*(++q)
不会“返回地址”。它返回类型int[4]
的结果,它是数组类型的左值。该左值是指数组a[1]
的{{1}}子数组。
这意味着您的问题的标题根本不准确:在这种情况下,取消引用运算符确实返回它应该返回的内容。指针被声明为指向数组的指针,而解除引用运算符的计算结果为 array 类型的左值。
然而,在此之后,您在衰减到指针类型的上下文中使用该数组左值,就像任何其他数组一样(参见What is array decaying?,Why do arrays in C decay to pointers?) 。将数组作为参数传递给a
恰好是这样的背景。因此,原始数组左值衰减到指针。该指针值指向printf
的开头,与a[1]
相同。该指针值传递给&a[1][0]
,您尝试使用printf
打印它。
(请注意,在%d
中使用%d
来打印指针值会触发未定义的行为。)
嗯,您可以以任何方式访问它们
printf
答案 1 :(得分:1)
此声明
int (*q)[4];
声明指向int[4]
类型对象的指针。为了简化理解,您可以通过以下方式引入typedef
typedef int T[4];
T *q;
q = a;
因此,取消引用指针,您将获得类型T
的指向对象,该对象表示类型为int[4]
的数组。结果在printf
函数
printf("\n%d\t%d",*(++p),*(++q));
^^^^^
你将获得数组++q
的第二个“行”(由于递增指针a
),而这又是int[4]
类型的一维数组隐式转换为指向其第一个元素的指针。
因此,表达式*(++q)
的类型为int *
,并指向数组a
的第二个“行”的第一个元素。
如果要使用此指针遍历数组a
的元素,可以按以下方式执行
#include <stdio.h>
int main(void)
{
int a[][4] = { { 2, 3, 4, 5 }, { 43, 32, 76, 3 } };
int ( *q )[4] = a;
for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
{
for ( size_t j = 0; j < sizeof( *q ) / sizeof( **q ); j++ )
{
printf( "%2d ", q[i][j] );
}
printf( "\n" );
}
return 0;
}
程序输出
2 3 4 5
43 32 76 3
即q[0]
是数组a
的第一个“行”。您也可以只写*q
。 q[1]
是数组a
的第二个“行”。您也可以像*( q + 1 )
一样撰写。要访问每行的元素,您可以应用下标运算符(第一行)
q[0][i]
其中i
是某个索引值。或者你也可以像( *q )[i]
并且喜欢(第二行)q[1][i]
或( *( q + 1 ) )[i]
像**q
这样的特殊表达式会产生数组a
第一行的第一个元素。
答案 2 :(得分:0)
TL; DR 回答,取消引用指向数组的指针会产生一个数组,该数组一旦作为函数参数传递,就会衰减到指向数组第一个元素的指针。因此,最终的值是指针类型(前者和后者是指向不同类型的指针,但它们仍是指针)。
那说,首先
printf("%u\t%u", (unsigned int)p,(unsigned int)q);
是依赖于实现的行为,因为指向整数的指针的转换是实现定义的。如果有的话,您可以将指针转换为uintptr_t
类型并使用PRIuPTR
格式说明符进行打印以打印该值。
其次,指针算术遵循数据类型。 q
是指向4 int
个数组的指针。一旦递增,它指向第一个数组。但是,在提供的格式说明符中存在不匹配。
printf("\n%d\t%d",*(++p),*(++q));
^^ ^^^^^^
详细说明,q
是指向数组的指针类型。取消引用会生成一个数组,现在一旦数组作为参数传递给函数,它就会衰减到指向数组第一个元素的指针。因此,基本上,您将指针作为参数传递给%d
格式说明符,这是不匹配,导致undefined behavior。
最后,关于对单个元素的访问,您可以使用
(*(q+m))[n]
- &gt;首先取消引用q
以获取数组,然后使用索引q[m][n]
- &gt; q[m]
生成数组,然后使用n
作为索引来获取单个元素。