免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: yazi0127
打印 上一主题 下一主题

[C] 请教:C语言函数的返回值类型能否为结构体? [复制链接]

论坛徽章:
0
11 [报告]
发表于 2010-01-26 17:25 |只看该作者
原帖由 daybreakcx 于 2010-1-26 17:23 发表

结构体返回的话一般来说都不会只有一个成员变量,所以一般返回后需要一个结构体变量接着它的返回值,就像2楼的程序一样,平时我一般都是这么干的,我认为这里就有一次整个结构体的拷贝,不知道你所说的是什么 ...


你给我解释拷贝过程 , 你将漏洞百出 , 无法自圆其说.

论坛徽章:
0
12 [报告]
发表于 2010-01-26 17:40 |只看该作者
原帖由 老手 于 2010-1-26 17:25 发表


你给我解释拷贝过程 , 你将漏洞百出 , 无法自圆其说.


返回的结构体就是根据该结构的大小,有几个字节拷贝出几个字节。
有怀疑可以看看编译出来的汇编。

C语言中一般不怎么玩,一般是传给函数一个结构体指针,由该函数修改这个结构。如果非要函数返回结构实体,也没问题。就是老一辈的程序员不太这么干而已。

论坛徽章:
0
13 [报告]
发表于 2010-01-26 17:42 |只看该作者
原帖由 wsw1wsw2 于 2010-1-26 17:40 发表


返回的结构体就是根据该结构的大小,有几个字节拷贝出几个字节。
有怀疑可以看看编译出来的汇编。

C语言中一般不怎么玩,一般是传给函数一个结构体指针,由该函数修改这个结构。如果非要函数返回结构实 ...


拷贝? 在返回之前还是之后 ?

论坛徽章:
0
14 [报告]
发表于 2010-01-26 17:45 |只看该作者
在之前, 拷贝的目的地在哪里 ?
之后 , 拷贝的源又在哪里?

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
15 [报告]
发表于 2010-01-26 18:00 |只看该作者
对"大"结构体 S :

1. 一个返回S的函数f:

S f(parameters) {
    S result;
    operation_on(&result, parameters);
    return result;
}

2. 一个f的调用点:
S s;
s = f(arguments);


-------- -------- -------- --------
有可能编译器实际上是这么实现的:

f的定义:
void f(S* presult, parameters) {
      operation_on(presult, parameters);
}

f的调用点:
S s;
f(&s, arguments);


标准好像没有要求这么实现, 但msvc和gcc都是这样干的, 当结构体足够"大"的时候。

所以, "因为返回结构体效率低, 应该添加一个结构体指针作为返回参数" 不一定是必要的。
有可能编译器会帮你做这个事情 —— 而且是高效的做。
编辑器才知道"大"的阈值, 什么时候应该进行这样的转换。

论坛徽章:
0
16 [报告]
发表于 2010-01-26 18:06 |只看该作者
刚才去生成了一个汇编看了一下,好像是调用者先在堆栈里头开结构体大小的空间,然后将地址送eax,后传入调用

论坛徽章:
0
17 [报告]
发表于 2010-01-26 18:11 |只看该作者
可是我还是认为经由函数操作后,调用者利用这个原先传入的自己堆栈中的地址值如果进行s = f(arguments)这样的操作的时候,需要把指针指向堆栈内的内容进行到s对应内存的拷贝,这里就消耗拷贝时间了

论坛徽章:
0
18 [报告]
发表于 2010-01-26 18:11 |只看该作者
FUNCTION_STRUCT ReturnStruct(void)
{
    FUNCTION_STRUCT internalData;
    internalData.m_Member1 = 1;
    internalData.m_Member2 = 2;
    strcpy(&(internalData.m_String[0]), "Hello World!\n");

    return internalData;
}


难道有人认为 internalData 就是拷贝之源 ?
那么按照一般的理解internalData可是在堆栈中生成的 , 如果是这样的话 ,函数一返回 , internalData岂不是没了.

"松饼熊"是正确的,他在2楼的程序实际上是这样的:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int    m_Member1;
    int    m_Member2;
    char m_String[20];
}FUNCTION_STRUCT;

void ReturnStruct(FUNCTION_STRUCT *internalData)
{
    internalData->m_Member1 = 1;
    internalData->m_Member2 = 2;
    strcpy(internalData->m_String, "Hello World!\n");   
}

int main(int argc, char *argv[])
{
    FUNCTION_STRUCT externalData;
    ReturnStruct(&externalData);
    
    printf("%d, %d, %s",
            externalData.m_Member1,
            externalData.m_Member2,
            &externalData.m_String[0]);
    
    system("AUSE");   
    return 0;
}



这跟 "OneWaterloo" 说的结构体大小没有关系 , 都是这样的.

[ 本帖最后由 老手 于 2010-1-26 18:14 编辑 ]

论坛徽章:
0
19 [报告]
发表于 2010-01-26 18:22 |只看该作者
of course

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
20 [报告]
发表于 2010-01-26 18:40 |只看该作者

回复 #18 老手 的帖子

原帖由 老手 于 2010-1-26 18:11 发表
这跟 "OneWaterloo" 说的结构体大小没有关系 , 都是这样的.


是吗?  你从汇编角度看看:

struct Point2D32S {
      int x;
      int y;
};
是怎么返回的?

struct Point2D16S {
      short x;
      short y;
};

struct atomic_t {
      int val;
};
又是怎么返回的?


然后再说说, 是否和结构体大小有关系。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP