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

2024-08-24 01:32

本文主要是介绍从数组传参看函数的调用和数组的存储情况,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先我们先上例程:

#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个字节读取堆栈的数据。


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

这篇关于从数组传参看函数的调用和数组的存储情况的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1101062

相关文章

Kotlin运算符重载函数及作用场景

《Kotlin运算符重载函数及作用场景》在Kotlin里,运算符重载函数允许为自定义类型重新定义现有的运算符(如+-…)行为,从而让自定义类型能像内置类型那样使用运算符,本文给大家介绍Kotlin运算... 目录基本语法作用场景类对象数据类型接口注意事项在 Kotlin 里,运算符重载函数允许为自定义类型重

Java调用Python的四种方法小结

《Java调用Python的四种方法小结》在现代开发中,结合不同编程语言的优势往往能达到事半功倍的效果,本文将详细介绍四种在Java中调用Python的方法,并推荐一种最常用且实用的方法,希望对大家有... 目录一、在Java类中直接执行python语句二、在Java中直接调用Python脚本三、使用Run

Python如何调用指定路径的模块

《Python如何调用指定路径的模块》要在Python中调用指定路径的模块,可以使用sys.path.append,importlib.util.spec_from_file_location和exe... 目录一、sys.path.append() 方法1. 方法简介2. 使用示例3. 注意事项二、imp

SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法

《SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法》在SQLyog中执行存储过程时出现的前置缩进问题,实际上反映了SQLyog对SQL语句解析的一个特殊行为,本文给大家介绍了详... 目录问题根源正确写法示例永久解决方案为什么命令行不受影响?最佳实践建议问题根源SQLyog的语句分

Pandas中统计汇总可视化函数plot()的使用

《Pandas中统计汇总可视化函数plot()的使用》Pandas提供了许多强大的数据处理和分析功能,其中plot()函数就是其可视化功能的一个重要组成部分,本文主要介绍了Pandas中统计汇总可视化... 目录一、plot()函数简介二、plot()函数的基本用法三、plot()函数的参数详解四、使用pl

C#如何调用C++库

《C#如何调用C++库》:本文主要介绍C#如何调用C++库方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录方法一:使用P/Invoke1. 导出C++函数2. 定义P/Invoke签名3. 调用C++函数方法二:使用C++/CLI作为桥接1. 创建C++/CL

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

Python正则表达式语法及re模块中的常用函数详解

《Python正则表达式语法及re模块中的常用函数详解》这篇文章主要给大家介绍了关于Python正则表达式语法及re模块中常用函数的相关资料,正则表达式是一种强大的字符串处理工具,可以用于匹配、切分、... 目录概念、作用和步骤语法re模块中的常用函数总结 概念、作用和步骤概念: 本身也是一个字符串,其中

Java数组初始化的五种方式

《Java数组初始化的五种方式》数组是Java中最基础且常用的数据结构之一,其初始化方式多样且各具特点,本文详细讲解Java数组初始化的五种方式,分析其适用场景、优劣势对比及注意事项,帮助避免常见陷阱... 目录1. 静态初始化:简洁但固定代码示例核心特点适用场景注意事项2. 动态初始化:灵活但需手动管理代