0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言函数为什么不能返回数组?

电子工程技术 来源:电子工程技术 2019-11-26 11:25 次阅读

C语言函数为什么不能返回数组?

在C语言程序开发中,我们不可以编写下面这样的代码:

char f(void)[8] { char ret; // 。。.fill.。。 return ret;}int main(int argc, char ** argv) { char obj_a[10]; obj_a = f();}

不可以编写这样的代码

这其实就是不能在C语言函数中返回数组。但是如果将数组定义在结构体里面,就可以将其返回了,例如下面这段C语言代码,请看:

struct s { char arr[10]; };struct s f(void) { struct s ret; // 。。.fill.。。 return ret;}int main(int argc, char ** argv) { struct s obj_a; obj_a = f();}

函数可以返回结构体

结构体 s 只有一个数组成员 arr,显然,函数可以返回结构体,即使结构体只有一个数组成员,这是为什么呢?

C语言没有严格意义上的“数组类型”

基本上,C语言中的数据结构可以分为两类,第一类数据结构可以被赋值,而第二类数据结构不可以被赋值,数组属于第二类数据结构。

除了数组,还有其他第二类数据结构吗?我想基本上没有了,除非把函数算上。与函数不能返回数组密切相关的事实是,C语言没有严格意义上的“数组类型”。可能从C语言代码角度来看,似乎有数组类型的变量,但是如果尝试将该变量像其他变量一样使用,得到的实际上是指向数组第一个元素的指针。例如下面这段C语言代码:

char a[10], b[10];a = b;

这并不能把数组 b 的内容拷贝给数组 a,实际上,上面两行C语言代码相当于下面这一行:

a = &b[0];

显然,左边是数组 a,而右边其实是一个指针。即使数组在某种程度上可以看作能够被赋值,但我们有很大几率得到类型不匹配,例如下面这段C语言代码:

a = f();

这里假设 f() 是一个返回数组的函数,它的核心C语言代码如下:

char ret[10];/* 。。. fill 。。. */return ret;

不过按照前面所说的,其实上面的返回语句相当于下面这一句:

return &ret[0];

同样的,我们若是尝试将数组赋值给 a,最终实际得到仍然是将指针赋值给 a,熟悉C语言语法的读者应该能够看出不妥之处。

为什么把数组塞入结构体,情况就不同了呢?

文章开头提到,虽然C语言的数组不可以被赋值,但是将其塞入结构体就可以赋值了。这是什么原因呢?

其实这涉及到C语言的设计初衷,以及相关的一些发展历史了。C语言在语法和语义上与机器硬件很接近,它的基本操作可以被编译为一个或者几个机器指令,占用若干个处理器周期。

C语言中的数组是特殊的,它与指针一直都是非常暧昧的。这种暧昧的关系从C语言的前身B语言就开始了,并一直延续至今,而今天的结构体语法最初并不是包含在C语言中的。

因为C语言数组与指针的暧昧关系,编译器也很难区分它们,所以我们不可能为C语言数组赋值。而且由于“赋值”操作也属于C语言的基本操作,为了贴合硬件,要求其必须在几个处理器周期完成,所以单个的“赋值”运算符 = 基本上不可能扩展到需要几千乃至几万个机器周期,以对成千上万个数组元素赋值。

基于这样的原理,早期的C语言其实连结构体赋值都是不支持的。

到这里,相信不少读者又有疑问了,既然C语言的基本操作需要控制在少量的机器周期内,那为什么结构体赋值却是支持的呢?毕竟C语言中的结构体也是可以包含多个字节信息的。

C语言中的结构体也是可以包含多个字节信息的

正如前文所说,早期的C语言的确不支持结构体赋值,但是在后来的发展中却增加了结构体赋值能力。对此只能说是结构体幸运,“将C语言基本操作控制在少量机器周期内”只是一个准则,而不是限制。

要知道,C语言结构体通常很小,只有几十到几百字节,增加结构体赋值能力无疑能够大大方便程序员编写代码。大多数情况下,结构体赋值操作并不会严重“超时”,这其实是一种平衡。

我之前的文章曾经讨论过,程序设计语言一般都要处理一个天平,天平的两端分别是机器和程序员,如果追求极致的机器效率,将编程语言设计的十分精简,那么程序员就会非常痛苦。因此,即使是C语言,在追求高效率的同时,也要兼顾程序员的感受,所以稍稍违背一些设计准则,增加一些便利操作也是无可厚非的。

小结

C语言不支持数组赋值,更多的原因是C语言本身的特点(贴合硬件)以及一些历史原因。不过,如果真的希望对数组赋值,也是有一些技巧的,例如将数组塞入结构体。这一点我之前的文章已经讨论过,不再赘述了。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • C语言
    +关注

    关注

    180

    文章

    7604

    浏览量

    136816
  • 函数
    +关注

    关注

    3

    文章

    4331

    浏览量

    62613
  • 代码
    +关注

    关注

    30

    文章

    4788

    浏览量

    68606

原文标题:为什么C语言函数不能返回数组,却可以返回结构体

文章出处:【微信号:EngicoolArabic,微信公众号:电子工程技术】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    同样是函数,在CC++中有什么区别

    值,即使没有数据返回,也得写 void。 第二个函数名。 C语言函数名绝对不能重名,除了用上
    的头像 发表于 11-29 10:25 307次阅读

    C语言中申请的堆内存能不能自动释放

    C语言中申请的堆内存能不能自动释放?每次都要手动 free 太麻烦,也容易忘记。 学过 C++ 的同学,应该首先能想到智能指针。 但是这是C
    的头像 发表于 11-27 09:33 116次阅读

    数组名之间可以直接赋值吗

    数组之间的赋值能不能直接使用等于号?比如这样的代码。 int main(){ int a[5] = {1, 2, 3, 4, 5}; int b[5] = {0}; b = a
    的头像 发表于 11-26 11:23 143次阅读

    C语言数组应用计算机导论A第6讲:数组

    C语言数组应用计算机导论A第6讲:数组
    发表于 11-20 15:33 0次下载

    常用SQL函数及其用法

    SQL(Structured Query Language)是一种用于管理和操作关系数据库的编程语言。SQL 提供了丰富的函数库,用于数据检索、数据更新、数据删除以及数据聚合等操作。以下是一些常用
    的头像 发表于 11-19 10:18 271次阅读

    解读版|Air780E软件中C语言内存数组的神秘面纱!

    今天我们来揭开Air780E 软件中 C 语言内存数组的神秘面纱,希望有所收获。
    的头像 发表于 11-17 10:00 251次阅读
    解读版|Air780E软件中<b class='flag-5'>C</b><b class='flag-5'>语言</b>内存<b class='flag-5'>数组</b>的神秘面纱!

    使用C语言实现函数模板

      用C语言不能实现一个通用的函数,既能完成整数的相加,又能完成浮点数的相加?
    的头像 发表于 11-09 11:38 387次阅读

    C语言中的socket编程基础

    数据 步骤6:关闭socket 创建socket 在C语言中,创建socket需要使用socket()函数。这个函数需要两个参数:域
    的头像 发表于 11-01 16:51 320次阅读

    C语言指针运算符详解

    C语言中,当你有一个指向数组中某个元素的指针时,你可以对该指针执行某些算术运算,例如加法或减法。这些运算可以用来遍历数组中的元素,如ptr[i]等价于*(ptr + i)。然而,如果
    的头像 发表于 10-30 11:16 254次阅读

    C语言指针详细解析

    。 二维数组 二维数组其实可以看成是一个矩阵,zai C语言中,定义一个数组num[3][4],可以看成是一个3行4列的矩阵,在内存中每一个
    发表于 09-14 10:03

    面试常考+1:函数指针与指针函数数组指针与指针数组

    在嵌入式开发领域,函数指针、指针函数数组指针和指针数组是一些非常重要但又容易混淆的概念。理解它们的特性和应用场景,对于提升嵌入式程序的效率和质量至关重要。一、指针
    的头像 发表于 08-10 08:11 861次阅读
    面试常考+1:<b class='flag-5'>函数</b>指针与指针<b class='flag-5'>函数</b>、<b class='flag-5'>数组</b>指针与指针<b class='flag-5'>数组</b>

    C语言中,同一个函数不能被定义两次?

    稍微有点C语言基础的同学,一定知道不能这样做。
    的头像 发表于 05-11 18:27 1710次阅读

    嵌入式系统中C语言结构体的基础实现与应用

    C语言中的数组只能允许程序员定义存储相同类型数据。但是结构是C语言编程中允许您存储不同数据类型的数据。
    发表于 03-12 14:29 502次阅读
    嵌入式系统中<b class='flag-5'>C</b><b class='flag-5'>语言</b>结构体的基础实现与应用

    C语言字符串编译函数介绍

    C语言中,字符串实际上是使用null字符O'终止的一维字符数组。因此,一个以null结尾的字符串,包含了组成字符串的字符。
    的头像 发表于 03-07 16:18 514次阅读
    <b class='flag-5'>C</b><b class='flag-5'>语言</b>字符串编译<b class='flag-5'>函数</b>介绍

    PHP中数组的使用方法!

    PHP中数组的使用方法! PHP是一种广泛使用的网络编程语言,它的数组功能非常强大且灵活。数组是一种数据结构,它允许我们在单个变量中存储多个值。 在本篇文章中,我将详细解释PHP
    的头像 发表于 01-12 15:11 550次阅读