鱼C论坛

 找回密码
 立即注册
查看: 2472|回复: 21

[已解决]关于数组的理解对吗?

[复制链接]
发表于 2024-1-20 12:35:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

例如数组 int arr[5];
在C语言中,数组一旦被声明,CPU就会立刻在内存中为其申请一块连续的、指定长度的内存空间(20个字节),用来存储该数组中各元素的值,此时,数组名arr(即标识符)代表了整块连续的内存空间,编译器在建立符号表时,会记录数组名(标识符)arr,数据类型 int [5] 和相应的首地址。当代码中引用了一个数组名时,编译器会通过符号表来查询到该标识符相应的内存地址(数组名在不和&和sizeof发生关系时,默认为首元素的地址),当用数组名作为函数的实参时,传递的是首元素的地址(址传递),形参实际上是一个指向数组首元素的指针变量,但并不会为形参开辟内存空间。

最佳答案
2024-1-20 15:31:11
竹逸 发表于 2024-01-20 15:30
可如果在声明函数时,函数的形参不是一个指针变量,而 ...


是的,当函数的形参声明为一个数组时,在函数内部实际上会将其转换为一个指针变量来处理。这是因为数组在函数参数中传递时会自动退化为指针。这个指针指向数组的首元素,而不是整个数组。

在函数内部,数组作为形参的时候并不会开辟新的内存空间来存储数组元素,只会开辟一个指针变量的大小来存储传递进来的数组的首地址。通过这个指针变量,我们可以访问传递进来的数组元素。下面是一个示例代码,用于演示数组作为函数形参的情况:

#include

void modifyArray(int arr[], int size) {            for (int i = 0; i < size; i++) {                arr[i] += 10;  // 修改数组元素的值            } }

int main() {            int arr[] = {1, 2, 3, 4, 5};            int size = sizeof(arr) / sizeof(int);             // 调用函数修改数组            modifyArray(arr, size);             // 输出修改后的数组            for (int i = 0; i < size; i++) {                printf("%d ", arr[i]);            }            printf("\n");            return 0; }

输出:11 12 13 14 15

在这个例子中,modifyArray函数的形参声明为int arr[],但在函数内部实际上它被处理为一个指针变量,指向传递进来的数组arr的首元素。我们可以通过这个指针变量来访问和修改原始数组的元素。

希望这个例子能够帮助你理解数组作为函数形参时的情况。如果还有其他问题,请随时提问!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2024-1-20 13:04:29 From FishC Mobile | 显示全部楼层
FishC 发表于 2024-1-20 12:36
对的,你对数组的理解是正确的。

在C语言中,一旦声明了一个数组,CPU就会为其在内存中分配一块连续的内 ...

既然形参是一个指向数组首元素的指针变量,虽然不会为形参开辟与原始数组相同长度的内存空间,但作为该指针变量本身,会开辟一个指针型长度的空间用来存储首元素的指针吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 15:30:23 From FishC Mobile | 显示全部楼层
FishC 发表于 2024-1-20 14:08
是的,形参作为一个指针变量本身,在函数内部会开辟一个指针的大小(通常4或8个字节,取决于操作系统) ...

可如果在声明函数时,函数的形参不是一个指针变量,而是一个数组,那形参数组在本质上也是会当成一个指针变量看待来开辟一个指针型空间吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 15:50:21 From FishC Mobile | 显示全部楼层
jackz007 发表于 2024-1-20 13:36
下面的表述只要把红字删掉就对了。
        当用数组名作为函数的实参时,传递的是首元素的地址( ...

你这么说也没错的,可是既然接收到的是一个地址值,应该是有一个空间来存储这个接收到的地址啊
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 18:35:38 | 显示全部楼层
人造人 发表于 2024-1-20 16:27
对,形参有地址,是一个变量
形参和局部变量唯一的区别就是,形参是调用函数的时候初始化,而局部变量需 ...

无论是主函数main中的局部数组data,还是函数a中的局部指针变量data,都是在函数体内声明的,那应该都是从栈中开辟的内存空间,而分配栈内存的特点是:先定义的变量分配高地址,后定义的变量分配低地址,即从高地址向低地址分配,原因是栈内存从上往下的地址值是由小到大的,即地址值是上低下高,而栈顶寄存器永远都是指向栈顶元素(当初始栈为空的时候,栈顶指向的是最高偏移地址的下一个单元),数据存储在栈中是入栈的操作,执行步骤是栈顶首先会空出内存单元,即栈顶指向的地址值减去所存储数据的长度,得到的新地址就成为的新的栈顶(也是当前所存数据的首地址),然后开始传送数据。

而主函数main是优先执行的,你说的形参初始化的时间比局部变量早一些是指开辟内存空间的先后吗?
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 18:39:31 | 显示全部楼层
人造人 发表于 2024-1-20 16:41
函数的参数就是个局部变量

帮我看看我对于物理地址和变量的理解对了吗?

关于物理地址的理解:

内存中每一个字节(字节也叫存储单元)都是以线性排列的,为了方便区分各个相互独立的字节,我们用记编号的方式来定位每一个字节,第一个字节从0开始编号,那么第二个字节的编号就是1,以此类推,这些编号就是每一个字节在当前位置的地址值,每一个字节(即存储单元)在物理层面上都是实实在在存在的,所以把为这些字节分配的地址值称为物理地址。

关于变量的理解:

在C语言中,变量一旦被声明,CPU就会立刻在内存中为其申请一块内存空间,用来存储该变量的值,那么变量本质上就是这块申请的内存空间,变量名就是该内存空间的名称(变量名就代表了该内存空间),变量的地址就是该内存空间的内存地址(地址值),编译器在编译的过程中会建立符号表,用于记录该内存空间的名称(即变量名,也叫标识符)和相应的内存地址及数据类型,当代码中引用了一个变量名时,编译器会通过符号表来查询该变量名相应的内存地址,然后通过这个地址值与数据类型来定位到相应长度的内存空间进行存取数据的,所以在程序运行时,cpu是直接通过内存地址来访问变量(内存空间)的,而不是变量名(变量名是为了方便人类的理解和维护的,在计算机内部会被替换成相应的内存地址。所以声明变量,其实就是声明了一块指定长度的内存空间,数据类型的作用就是指定这块内存空间的长度的)。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 19:08:15 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-1-20 16:27
对,形参有地址,是一个变量
形参和局部变量唯一的区别就是,形参是调用函数的时候初始化,而局部变量需 ...

X﹏X,我现在好像理解你说的意思了,你的意思是说形参在函数调用时,自带初始化值,也就是实参作为形参的初始化值,而局部变量要自己手动赋值一个初始化值,是这个意思吧(=TェT=)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-20 20:27:20 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-1-20 19:36
可以这么理解,最好是学一下汇编语言
你的这个问题全在汇编代码里面了

以前学过几章就没学了,只懂得一点点,所以看不懂汇编语言(-﹏-`;)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-1-21 07:49:02 From FishC Mobile | 显示全部楼层
人造人 发表于 2024-1-20 22:15
用C语言和汇编语言,自己写代码把逻辑地址转换成线性地址,把线性地址映射到物理地址
让一个程序调用fork ...

对于底层原理不了解的话,在碰到一些抽象却又至关重要的问题时学习起来确实比较辛苦,c语言我以前是学过一遍的,学完了就懒了没有继续学了,现在又是重新开始学习了,好在每次重新学习时都有更多的理解,也算起到查漏补缺的作用吧,现在准备二维数组的内容(*︶*)
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-9-22 15:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表