C语言数组退化问题和改进

目录

前言

提醒

问题表现:

[解析 :](#解析 :)

注意:

解决方案:

思考一下:

改进:

下期预告:C语言移位运算问题


前言

这篇文章我们就来梳理一下关于数组的陷阱,这类陷阱的中招率还是挺高的,这就是因为在当数组做函数参数时的退化问题,导致你想的和编译器执行的不同而导致的错误,下面就让我们看一看问题出在什么地方,只有理解了问题的所在和引起问题的条件我们才能避免下一次的中招,并且改进这种方法以此来规避陷阱,达到有效的编译。


提醒

首先我们要明确一下数组在一定的访问条件时,编译器会将数组名认为是++指针++ 来访问++数组首元素++。

这就意味着你可以使用数组名来访问数组中的元素,就像使用指针一样。

但是还是会有++不同点++:

  1. 类型不同:数组类型明确指出了数组的大小和元素的类型,比如int arr[10];表示一个有10个整数的数组。而指针只是指向某种类型的变量,比如int* ptr;表示ptr是一个指向整数的指针,但它不直接说明指向的整数有多少个。
  2. 内存分配:数组在声明时会在++栈上或静态存储区++ 分配一块连续的内存空间,用于存储数组的所有元素。而指针本身是一个变量,通常存储在栈上,但它指向的内存空间可以是在++栈上、堆上或静态存储区++,这取决于指针是如何被初始化的。
  3. 运算:虽然数组名和指针在很多情况下可以互换使用,但在进行某些运算时,它们的行为会有所不同。比如,++对数组名进行sizeof运算会得到整个数组的大小,而对指针进行sizeof运算则只得到指针本身的大小++(通常是4或8字节,取决于系统架构)。
  4. 数组名作为函数参数:++当数组名作为函数参数时,它会被退化为指向数组首元素的指针。这意味着,在函数内部,你无法直接获取到数组的大小信息。++
  5. 指针的指针:指针可以指向另一个指针,这种结构在动态数组(如通过malloc或new分配的内存)的管理中非常有用。而数组名则不能进一步"退化"为指向指针的指针。

总的来说,虽然数组和指针在C++中紧密相关,但它们各自有着独特的特性和用途。理解它们之间的区别和联系,对于编写高效、安全的C++代码至关重要。


问题表现:

数组在++作为函数参数++时的退化,导致结果和预期不同。

你是否看到了绿色的字,这就是这篇文章主要说的问题,数组退化成为指针。我们都知道数组是存放一些列数的组合,但是当退化成为指针的时候就会将数组变成单一的一个元素(数组的首元素)来进行编译从而导致错误的发生,这类错误一般是在写函数时让数组++直接成为函数参数++而发生的问题,下面来看一段代码:

cpp 复制代码
include<iostream>
using namespace std;

int average1(int arr[10])
{
int s=0;
int len=sizeof(arr)/sizeof(arr[0]);
cout<<"in average"<<len<<endl;
for(int i=0;i<len;i++)
{
s+=arr[i];
}
return s/len;
}

int main()
{
int array1[]={10,20,30,40,50,60,70,80,90.100};
int len=sizeof(array1)/sizeof(array[0]);
cout<<"in main"<<len<<endl;
cout<<average1(array1)<<endl;

return 0;
}

上面的代码我们输出的结果有三行,1,10,10;我们可以计算器算一下这十个数求和后求平均数的结果应该是55,但是我们的结果显示却是10,这里就是问题。我们前文说到当直接把数组做为函数的参数那么数组就会退化成为指针而且该指针指向的时数组的首元素,那么你想到答案了吗?

解析 :

看代码,当数组带入函数时结果就是只将数组的首元素带入了函数,从而导致结果出错,我们以为的是数组会整体带入到函数中,可实际上数组只是将首元素传入了函数,这就是陷阱。所以我们在函数中求的数组长度和主函数的数组长度不同,在函数中只是求了数组首元素的长度(结果是1),在主函数中求的是数组的整体长度(结果是10)。所以结果会偏差巨大,这就是原因。

总结:当数组直接作为函数的参数时,数组会退化成为指针。

注意:

数组本身是不变的;变得只是传入函数时的数组,主函数定义的数组是不变的。


解决方案:

这种陷阱很容易中招也很容易破招。看下面代码:

cpp 复制代码
include<iostream>
using namespace std;

int average2(int arr[10],int len)
{
int s=0;
for(int i=0;i<len;i++)
{
s+=arr[i];
}
return s/len;
}

int main()
{
int array1[]={10,20,30,40,50,60,70,80,90.100};
int len=sizeof(array1)/sizeof(array[0]);
cout<<average2(array1)<<endl;

return 0;
}

问题的关键就是数组退化成指针,数组的长度变化,导致我们在函数中运算错误,所以解决问题的方法就是给函数设置新的参数(数组的长度),一切就都可以解决。这就是陷阱的解决方案,是不是很简单。

思考一下:

这是整型,浮点型数组的实例,如果我们将整型变为字符型,就是将字符类型的数组带入函数,那么该怎么?代码添加或减少的部分是什么?结合上期内容思考一下。(答案下期揭晓)

改进:

这是C语言的解决方法,那么C++的方法是什么呢?作为C语言的改进语法,C++中的解决方法就简单的多,那利用就是++STL里的vector库++来解决,关于STL的用法会在后期详细说到,上面的解决方法也是很简单实用的。

🆗到这里,这篇关于数组退化成指针的陷阱就说完了,求一个免费的赞,感谢阅读。

下期预告:C语言移位运算问题
相关推荐
ALISHENGYA几秒前
全国青少年信息学奥林匹克竞赛(信奥赛)备考实战之分支结构(实战项目二)
数据结构·c++·算法
蜗牛hb3 分钟前
VMware Workstation虚拟机网络模式
开发语言·学习·php
arong_xu13 分钟前
现代C++锁介绍
c++·多线程·mutex
汤姆和杰瑞在瑞士吃糯米粑粑18 分钟前
【C++学习篇】AVL树
开发语言·c++·学习
Biomamba生信基地25 分钟前
R语言基础| 功效分析
开发语言·python·r语言·医药
DARLING Zero two♡26 分钟前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
手可摘星河28 分钟前
php中 cli和cgi的区别
开发语言·php
CodeClimb40 分钟前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
CT随1 小时前
Redis内存碎片详解
java·开发语言
anlog1 小时前
C#在自定义事件里传递数据
开发语言·c#·自定义事件