从数组传参看函数的调用和数组的存储情况

首先我们先上例程:

#include <stdio.h>#define SIZE 10/* 数组为 int 类型的数组*/const int date[SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};int Sum(unsigned char *ar);void main( void ){int date_sum = 0;date_sum = Sum(date);printf("将数组的数相加等于:%d\n", date_sum);}/*形参为 unsigned char 类型*/int Sum(unsigned char *ar){int i;int total = 0;/* 先打印出 ar 的地址*/printf("ar(a[0])的首地址:%x\n\n", ar);for(i=0; i<SIZE; i++){/* 打印出数组的地址和值*/printf("数组ar[%d]地址:%x 值:%d\n", i, &ar[i], ar[i]);total += ar[i];}return total;}

运行结果为:

本应输出的结果应为:0+1+···+9 = 45

而实际输出的结果却为3,这是为什么呢,让我们先看看函数调用的过程。

函数调用过程:

调用函数首先把参数放在堆栈的临时存储区域中,然后被调函数从堆栈中读取这些参数。但这两个过程并没有相互协调进行,调用函数传递的是实参的类型,而被调用函数则是按照其形参的类型进行数据读取。

从函数调用的原理我们可以看出:调用函数先将 int 类型的数组data[SIZE] 放入首地址为 0x00422fa8 的内存当中,,我们用 memory 窗口可观察 0x00422fa8 ~ 0x00422fcb 这部分内存所存储的值,因为数组类型为 int 类型,所以一个元素占4个字节。

而被调函数则是按形参声明的类型类调用堆栈里的数据的,形参声明的类型是 char 类型,所以形参是 1字节1字节 的调用堆栈里的数据的,所以程序 for 循环中调用了10次数组的值相加也只是将 0X00422FA8 ~ 0X00422FB1 的值相加而已,所以导致程序得出错误的结果。

而我们将例程中的:

int Sum(unsigned char *ar);改为:int Sum(int *ar);

运行的结果为:

则它将会每隔4个字节读取堆栈的数据。

从这个易错的例子我们可以很好的理解:函数调用的过程、数组在内存中的存储、数组和指针等问题。

这一次是一个告别,或者一个永远的告别,

从数组传参看函数的调用和数组的存储情况

相关文章:

你感兴趣的文章:

标签云: