龙空技术网

GNU11与C++14如何返回一个匿名结构体对象

陳小萌zennychen 417

前言:

如今同学们对“c语言返回一个结构体”都比较关切,各位老铁们都想要剖析一些“c语言返回一个结构体”的相关知识。那么小编也在网络上搜集了一些关于“c语言返回一个结构体””的相关内容,希望我们能喜欢,咱们一起来了解一下吧!

我们在用C/C++写程序的时候,有时想在一个函数里返回一个多值对象。在传统C语言中,通常方式是把要返回的对象以形参通过指针的方式进行写回。而对于C++,除了这种方式之外,还可以借助STL标准库中的 std::pairstd::tuple 等容器类进行返回。

而本文将为大家介绍另一种方式——通过匿名结构体类型来返回一个多值对象。使用匿名结构体有不少好处。首先是避免全局名字空间的污染。毕竟对于一个比较大的项目工程而言,外部定义的类型已经够多了,所以对于内部模块所使用的复合类型而言,能少定义一个是一个~这对于基于C语言为主的项目而言尤为有用。当然,使用形参指针进行写回的方式尽管是非常常用的,我们可以从OpenGL、OpenCL、CUDA等著名的API中都能看到这种方式的缩影,但这往往会使得参数列表过长,代码可能会变得难看一些。

GNU11实现一个匿名结构体对象的返回与获取

对于C语言,C99就能允许函数返回类型为一个匿名结构体或联合体对象类型。不过由于缺乏类型自动推导,因此要在函数调用处去获取该匿名结构体对象是无法做到的。而从GCC 4.9 版本起,Clang 3.8 版本起,两大主流编译器均引入了 __auto_type 关键字,使得C语言中也能直接使用类型自动推导系统。这么一来就能轻松获取函数所返回的匿名结构体对象了。下面笔者就为大家举一些例子:

// 以下两个头文件包含为Android NDK使用的头文件,其他项目可以屏蔽#include <jni.h>#include <syslog.h>#include <stdio.h>#ifndef let#define let     __auto_type#endif/** * 定义一个返回匿名结构体对象的函数FuncFoo * @param n 输入参数 * @return 一个匿名结构体对象 */static struct { double d; int i; char c; } FuncFoo(int n){    // 通过GNU语法扩展中的typeof()来获取FuncFoo函数的返回类型    typeof(FuncFoo(0)) const result = {        .d = 10.5,        .i = n + 1,        .c = 'z'    };    return result;}static void CTest(void){    // 通过GNU语法扩展的类型自动推导来获取FuncFoo所返回的匿名结构体对象    let const value = FuncFoo(9);    // 输出:value.d = 12, value.i = 10, value.c = 'z'    // 其他平台可用printf来代替此syslog函数    syslog(LOG_INFO, "value.d = %d, value.i = %d, value.c = '%c'",           (int)(value.d + 1.5), value.i, value.c);}

上述代码基于Android Studio Dolphin 2021.3.1进行编写,通过Android Studio内置的NDK通过编译并能运行。这里给Windows系统用户推荐使用Android Studio来把玩基于Linux系统下的C语言相关的代码测试,由于用的是与时俱进的Clang编译工具链,所以还是非常好用的。因此也非常适合测试基于GNU语法扩展的C语言。

借助强大IDE,我们也能看到通过自动化文档以及智能感知等现代化工具来查看、编写代码,这也是非常便利的。

下面展示一个Android Studio的截图。当我们将鼠标光标停留在如下图所示的 FuncFoo 位置处,IDE就会弹出其文档化的对话框。

C++14实现一个匿名结构体对象的返回与获取

这里首先要为大家阐明重要的一点:C++标准里不允许将一个匿名结构体(以及联合体或类)类型作为函数的返回类型。因此,如果我们在C++中要定义一个返回类型为匿名结构体的函数的话,需要借助C++11开始所引入的类型自动推导系统,因而直接使用 auto 关键字来声明其返回类型。

正因如此,这类函数只能直接进行定义,而不能声明!比如像:

extern auto Foo();

这种函数声明形式是非法的。

不过C++14中使用返回类型为匿名结构体的函数比起上面的基于GNU语法扩展的C语言要干净整洁得多。我们下面来看一个例子:

#include <cstdio>/** * @brief 定义一个返回匿名结构体对象的函数FuncFoo * @param n 输入参数 * @return 一个匿名结构体对象 */static auto FuncFoo(int n){    const struct { double d; int i; char c; } result = {        .d = 10.5,        .i = n + 1,        .c = 'z'    };    return result;}extern "C" auto CPPTest(){    auto const value = FuncFoo(9);    // 输出:value.d = 12, value.i = 10, value.c = 'z'    printf("value.d = %d, value.i = %d, value.c = '%c'",        int(value.d + 1.5), value.i, value.c);}

下面再给出Visual Studio 2022 Community Edition下的代码截图。

从上图我们确实可以看到,Visual Studio的智能感知的代码提示还是非常友好的。

标签: #c语言返回一个结构体