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语言移位运算问题
相关推荐
一个小坑货6 分钟前
Cargo Rust 的包管理器
开发语言·后端·rust
bluebonnet2710 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
古月居GYH11 分钟前
在C++上实现反射用法
java·开发语言·c++
Betty’s Sweet13 分钟前
[C++]:IO流
c++·文件·fstream·sstream·iostream
敲上瘾27 分钟前
操作系统的理解
linux·运维·服务器·c++·大模型·操作系统·aigc
不会写代码的ys33 分钟前
【类与对象】--对象之舞,类之华章,共绘C++之美
c++
兵哥工控36 分钟前
MFC工控项目实例三十二模拟量校正值添加修改删除
c++·mfc
在下不上天36 分钟前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
长弓聊编程1 小时前
Linux系统使用valgrind分析C++程序内存资源使用情况
linux·c++
陌小呆^O^1 小时前
Cmakelist.txt之win-c-udp-client
c语言·开发语言·udp