数组和指针可交换性的讨论

    技术2022-05-20  53

    一、

    数组和指针是有区别的。

    若存在这种情况,

    file1:

    int age[100];

     

    file2:

    extern int *age;

     

    这样,对age声明与定义出现了二义性,编译器会报错。

     

    c语言标准作出说明:

    规则 1.表达式中的数组名(与声明不同)被编译器当作一个指向该数组第一个元素的指针

    规则 2.小标总是与指针的偏移量相同

    规则 3.在函数参数的声明中,数组名被编译器当作指向该数组第一个元素的指针。

     

    数组作为形参时,编译器的行为:

    数组形参是怎么样被引用的?

     

    所有属于函数实参的数组在编译时被编译器改写为指针。因此,在函数内部对数组参数的任何引用都将产生一个对指针的引用。

     

    没有办法把数组本身传递给一个函数,因为它总是被自动转换为指向数组的指针。

     

    数组和指针可交换性的总结:

    1.用a[i]这样的形式对数组进行访问总是被编译器“改写”或解释为像*(a+1)这样的指针访问

    2.指针始终是指针。它绝不可以改写成数组。你可以用下标形式访问指针,一般都是指针作为函数参数时,而且你知道实际传递给函数的是一个数组。

    3.在特定的上下文中,也就是作为函数参数的数组始终会被编译器修改成为指向数组第一个元素的指针。

    4.当把一个数组定义为函数的参数时,可以选择把它定义为数组,也可以定义指针。不管选择哪种方法,在函数内部事实上获得的都是一个指针

    5.在其他所有情况中 ,定义和声明必须匹配。如果定义了一个数组,在其他文件对它进行声明时也必须把它声明为数组。若是指针,亦然。

    二、例子

    在这里给出数组和指针作为函数参数传递的情况是可以互换的。

    在作为函数参数的时候,一个数组的声明可以看作是一个指针。

     

     看下面的例子:

    #include <stdio.h> char ga[] = "hello,world!"; void foo(char ca[20]) { printf("&ca = %#x, &(ca[0]) = %#x, &(ca[1]) = %#x/n", &ca, &(ca[0]), &(ca[1])); }// &ca是“形参ca”的地址,函数栈的地址范围内. &(ca[0]):全局数组变量的第一个成员的地址 void foo2(char *pa) { printf("&pa = %#x, &(pa[0]) = %#x, &(pa[1]) = %#x/n", &pa, &(pa[0]), &(pa[1]));//在linux系统中,foo2的函数栈覆盖foo的函数栈,所以&pa = &ca,值为虚拟空间的的地址,&(pa[0])的地址也是全局数组变量的第一个成员的地址 } int main(void) { foo(ga); foo2(ga); printf("int main() /n"); printf("&ga = %#x, &(ga[0]) = %#x, &(ga[1]) = %#x/n",&ga, &(ga[0]), &(ga[1])); return 0; } 

     

    在我的机器上(ubuntu9)的运行结果为:

     

    &ca = 0xbffb6c70, &(ca[0]) = 0x804a018, &(ca[1]) = 0x804a019 &pa = 0xbffb6c70, &(pa[0]) = 0x804a018, &(pa[1]) = 0x804a019 int main() &ga = 0x804a018, &(ga[0]) = 0x804a018, &(ga[1]) = 0x804a019  

     

     

     

     

    参考文献:《C专家编程》  Peter Van Der Linden著 徐波译


    最新回复(0)