【问题标题】:Do all C compilers allow functions to return structures?是否所有 C 编译器都允许函数返回结构?
【发布时间】:2010-03-10 19:10:55
【问题描述】:

我正在使用 C 语言编写程序,并将 SDCC 编译器用于 8051 架构设备。 我正在尝试编写一个名为 GetName 的函数,该函数将从闪存中读取 8 个字符并以某种形式返回字符数组。我知道不可能在 C 中返回一个数组,所以我尝试使用这样的结构:

//********************FLASH.h file*******************************
MyStruct GetName(int i);  //Function prototype

#define NAME_SIZE  8

typedef struct
{
    char Name[NAME_SIZE];
} MyStruct;

extern MyStruct GetName(int i);


// *****************FLASH.c file***********************************
#include "FLASH.h"

MyStruct GetName( int i)
{
     MyStruct newNameStruct;

     //...
     // Fill the array by reading data from Flash 
     //...

     return newNameStruct;
}

我还没有对此函数的任何引用,但由于某种原因,我收到一个编译器错误,提示“函数无法返回聚合”。这是否意味着我的编译器不支持返回结构的函数?还是我只是做错了什么?

【问题讨论】:

  • 自语言发明以来,C 编译器一直按值返回结构。你的问题就是 KennyTM 所说的。
  • 函数原型需要在函数调用之前出现!
  • @Jordan:把函数原型放在main之前之前,而不是之后。
  • 我已经做了所有这些更正,仍然没有运气。

标签: c struct 8051 sdcc


【解决方案1】:

SDCC doesn't support assignment and returning structs yet(如果他们的 Wiki 是最新的):

尚未在 sdcc 中实现:

  • 双精度数据类型。
  • 结构和联合不能被赋值、作为函数参数或返回值传递。
  • 在函数参数中注册存储类说明符。

也许你应该做一个

void GetName(MyStruct* ret_name, int i);

改为函数。


也就是说,您应该将函数原型 之前 放在 main之后 @987654324 @。如果没有原型,则假定函数返回 int

MyStruct GetName(int i);
void main(void) { ...

(另外,main 函数应该是 int main(void)int main(int argc, char** argv)。它不应该返回 void。)

【讨论】:

  • 对不起,我没有提到它,但我确实有一个与我上面的原型相匹配的原型......
  • 这仍然不是正确的完整代码,因为 MyStruct 的定义出现在原型之后,无法编译。在此处订购事项确切地向我们展示您要编译的内容。
  • 关于原型的说法并不完全正确。在这种情况下,OP 可能很容易摆脱非原型声明MyStruct GetName()。编译器将假定它返回一个int,即使它没有原型。实际上,大多数帖子都错误地使用了术语 prototype 来代替术语 declaration
  • 我试过你的建议使用 void GetName(MyStruct* ret_name, int i);如何为 ret_name 中的数组赋值?
  • +1 用于传递指向结构的指针而不是返回一个巨大的结构。
【解决方案2】:

所有后 ANSI C89/90 编译器都允许返回结构对象。经典(迂腐)的 K&R C 编译器没有。

但是,无论如何,您都必须先声明函数。即你调用它之前。并且您的结构中的char[8] Name 不是有效的声明。有效形式为char Name[8]

您的指向数组返回函数的声明正确。损坏的是您的尺寸宏。应该是

#define NAME_SIZE 8 

注意:没有= 字符。

【讨论】:

  • 对不起,你错了。 K&R 编译器,至少我用过的所有编译器,都按值返回结构。
  • @Neil Butterworth:无论您使用什么,都将结构分配实现为扩展。 “规范” K&R C 不允许结构分配和结构传递/按值返回。 en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
  • @AndreyT 请提供参考。
  • @Neil Butterworth:我希望这能做到en.wikipedia.org/wiki/C_(programming_language)#K.26R_C(见本节末尾)
  • @AndreyT 很公平,我猜我使用的所有 pre-ANSI 编译器都来自“AT&T 和其他一些供应商”。我丢失了多年前第一次编辑的 K&R 副本,因此无法轻易查看它的内容。
【解决方案3】:

是的,函数可以在 C 中返回结构。您上面的代码有几个错误。通过一些更改,它在 gcc 下正确编译(我没有安装 sdcc 来尝试,但请尝试下面的代码。

 struct MyStruct
 {
   char Name[8];
 }; 

 struct MyStruct GetName( int i)
 {
      struct MyStruct newNameStruct;

      //...
      // Fill the array by reading data from Flash 
      //...
     return newNameStruct;
 } 


 int main(void)
 {
     int NameIndex = 3;
     struct MyStruct testStruct;
     testStruct = GetName(NameIndex);
     return 0;  
 }

【讨论】:

    【解决方案4】:

    我真的不想使用没有实现结构调用和按值返回的 C 编译器,正如 KennyMT 建议的那样,您的编译器不会。事实上,这样的编译器不应该真正被称为 C 编译器。如果编译器完全实现了结构,那么按值返回并不难实现。

    无论如何,要使用您的编译器,您将需要以下内容:

    typedef struct
    {
        char Name[NAME_SIZE];
    } MyStruct;
    
    void f( MyStruct * m ) {
       strcpy( m->Name, "foo" );
    }
    
    int main() {
        MyStruct ms;
        f( & ms );
        return 0;
    }
    

    【讨论】:

    • 好的,我试过了,现在我得到一个链接器错误,说“?ASlink-Error-Could not get 29 Continuous bytes in internal RAM for area DSEG”什么是DESG?
    • @Jordan 我想也许是时候坐下来阅读您的编译器和链接器手册了。您使用的硬件和软件似乎远非标准,因此在这里提出更多问题可能不会让您走得太远,
    猜你喜欢
    • 1970-01-01
    • 2020-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 2021-04-06
    • 1970-01-01
    相关资源
    最近更新 更多