c语言 - 为什么在下面的函数中增加数组"a"不是错误?


#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代码相同的行为,paprintd()侧的行为类似于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'。

最新更新