指针数组与数组指针
@(c/cpp)
58笔试遇到一道题:
判断以下程序是否正确:
void fun(int num, char *a[])
{
for (int i = 0; i < num; i++)
{
printf("%s\n", a[i]);
}
}
int main()
{
char a[5][20];
strcpy(a[0], "asd");
strcpy(a[1], "zxc");
fun(2, a);
}
这其实是考察指针数组与数组指针的区别。
首先我们要很清楚:
char *a[20]
是个数组。数组中有20个元素。每个元素是个char*
的指针。
char (*a)[20]
是个指针。这个指针指向一个数组。数组有20个元素。每个元素是个char。
再看我们在主函数定义的char a[5][20]
,是个二维数组。
二维数组中其实重要的是后面一维。前面的数字是可以省略的。即可以写成char a[][20]
或者char (*a)[20]
。注意这里(*a)
是有括号的。
为什么呢?
因为对一个指针a
而言,最重要的是要知道a+1
指向哪。
在我们这个题目中,a
是指向一个数组,那好,请问a+1
指到哪去了?是下一个数组。
下一个数组的起始位置在哪?要知道下一个数组的起始位置,我们必须告诉编译器,这个数组有多长:char (*a)[20]
或char[][20]
在这个题目中,一个数组是20个char
这么长。
- | 0 | 1 | 2 | 3 | … | 19 |
---|---|---|---|---|---|---|
a-> | a | s | d | \0 | … | … |
a+1-> | z | x | c | \0 | … | … |
由此可见,题目的代码有错,传进去的a应该是数组指针而不是指针数组。
编译题目的代码会报错:
string.c:4:6: note: expected ‘char **’ but argument is of type ‘char (*)[20]’
void fun(int num, char *a[])
什么意思呢?就是按照这个函数的定义,应该传进来一个char **
,但是我们的主函数却传进去一个char (*)[20]
。
函数的定义char *a[]
其实相当于char **a
这是一个二重指针,指针数组。数组中的每个元素都是个char*
的指针。
那么问题就来了。a[0]
是啥?那应该是第一个char*
指针,a[1]
则是第二个char*
指针。
这跟我们定义的数据完全不是一回事啊。因此肯定会出错。
函数fun应该写成void fun(int num, char (*a)[20])
正确的代码就是把指针数组改成数组指针:
void fun(int num, char (*a)[])
{
for (int i = 0; i < num; i++)
{
printf("%s\n", a[i]);
}
}
int main()
{
char a[5][20];
strcpy(a[0], "asd");
strcpy(a[1], "zxc");
fun(2, a);
}