#include<stdio.h>
void printd(char []);
int main(void){
char a[100];
a[0]='a';a[1]='b';a[2]='c';a[4]='d';
printd(a);
return 0;
}
void printd(char a[]){
a++;
printf("%c",*a);
a++;
printf("%c",*a);
}
解释:我预料这会导致左值错误。但它的工作没有任何错误,并给出bc作为输出。为什么这个递增数组"a"不是一个错误?
如果将数组传递给函数,则将衰变成指向该数组第一个元素的指针。
因此,在printd()
内部,指针a
可以递增和递减,以指向main()
中定义的数组a
的不同元素。
请注意,当为任何类型T
声明/定义函数的形参列表时,表达式T[]
等同于T*
。
问题的具体情况
void printd(char a[]);
与
相同void printd(char * a);
下面的代码显示了与OP代码相同的行为,pa
在printd()
侧的行为类似于a
:
#include <stdio.h>
int main(void)
{
char a[100];
a[0]='a';a[1]='b';a[2]='c';a[4]='d';
{
char * pa = a;
pa++;
printf("%c", *pa);
pa++;
printf("%c", *pa);
}
return 0;
`}
在C语言中,函数形参表中的数组声明和函数形参表外的数组声明是完全不同的,尽管它们表面上看起来相似(或相同)。
当您在函数参数列表中使用数组声明时(如代码中的void printd(char a[])
),您是而不是声明数组。函数参数列表中的顶级[]
语法只是指针声明的另一种形式。这意味着您的a
参数实际上被声明为char *a
。它根本不是一个数组,它是一个普通的指针。能够增加这样的a
没有什么不寻常的,这就是为什么你不会从中得到任何"左值错误"。
同时,main
中的a
是一个真正的数组。
数组作为指针传递给函数,该指针可以自增。
因此,在您的示例中,不可能在main()
函数中增加a
,因为a
是一个数组,不能增加。
但是,不管语法如何,printd()
函数中的a
是一个指针,因此可以自增。在printd()
中增加a
不会影响main()中的数组a
-尽管它们具有相同的名称,但它们是不同作用域内的不同实体。
为什么这个递增数组"a"不是错误?
在C语言中,数组作为指向任何函数的指针传递。这就是为什么没有错误。
main()
中的函数调用传递数组a
的名称作为参数,因为表达式中数组的名称计算结果为指向数组的指针。换句话说,表达式a
是指向数组a[]
(它的第一个元素)的指针。因此,它的类型是char *
,被调用的函数使用该指针(作为实参传递)间接访问数组的元素。
a
的第一个元素的地址时,a++
表示将数组的初始地址提前1
。这就是为什么第一个printf
打印b
,即数组a
的第二个元素。
a也可用作指针。它是指向数组第一个元素的指针。a++会增加指针的值。也就是说,在a++之后,a[0]或*a现在给你的是a[1]在增加之前给你的,即'b'。
注意,你不能将a[0]的值从'a'增加到'b'。检查是否在数组中使用了不同的值,比如'a, 'd', 'h', 'x'。