c功能链可能吗?

时间:2012-05-07 14:39:27

标签: c

我想知道在C(89/90)中是否可以链接函数调用,以及它在C spec中的定义。我认为这是不可能的,因为谷歌搜索没有提及它。

我之所以这么想是因为与我的一位朋友进行了相关的谈话,他告诉我,如果函数返回一个struct,你就不能在同一个语句中对所述struct执行任何操作;相反,您必须将函数的结果赋给变量,然后通过变量而不是直接从函数结果本身操作结构。这让我相信你也不能链接函数,但我似乎无法找到规范中讨论的这些限制。

编辑:对不起,我应该具体了解返回值。假设函数返回一个函数指针,是否可以取消引用并以流畅的方式在同一语句中调用结果?

例如,假设getFunc返回一个函数指针:

(*getFunc(getFuncParam))(otherFuncParam)

或在struct案例中,假设struct的{​​{1}}成员名为int

count

5 个答案:

答案 0 :(得分:6)

这是C中的链接功能:

post_process(process(pre_process(data)));

显然,你的朋友错了。只要函数通过接受和返回相同类型的值进行协作,您就可以将所有调用链接起来。

将此与

等对比
data.pre_process().process().post_process();

最大的区别在于C(没有封装,因此没有类)函数具有中心舞台,而在更现代的OO语言中它是对象得到更多的关注。

更新:无论每个功能可能返回什么,都可以链接。例如:

int increase(int x) {
    return x + 1;
}

typedef int (*increase_fp)(int);

increase_fp get_increase() {
    return increase;
}

int main(void) {
    printf("%d", get_increase()(1));
    return 0;
}

See it in action

答案 1 :(得分:3)

  

我的一个朋友,他告诉我,给定一个返回结构的函数,你不能在同一个语句中对所述结构执行任何操作

你的朋友是正确的,因为函数的返回值不能是赋值的目标(它不是左值)。 IOW,你不能做像

这样的事情
int foo(void) { int x = 5; return x; }
...
foo() = 6;

但是,如果函数的返回类型是结构或联合,则可以将组件选择运算符应用于返回值,例如

int x = foo().memb;

类似地,如果函数的返回类型是指向struct或union的指针,则可以编写

int x = foo()->memb;

如果返回值是指向另一个函数的指针,则可以调用其他函数,如下所示:

int bar(int x) { ... }
int (*foo)(int x) { return bar; }
int x = foo(x)(y); // or (*foo(x))(y) -- the result of foo(x) is 
                   // called with the argument y

尽管任何需要维护或调试代码的人都可能会严重打败你。

无法做的事情就像是

foo().memb= ...;
foo()->memb = ...;

无论如何都没有意义,因为foo返回的值的生命周期在语句结束时结束 - 您将无法检索该修改后的值。

答案 2 :(得分:2)

你的朋友错了。

如果我们有:

struct Point3
{
   float x, y, z;
};

const Point3 * point3_get_origin(void);
那么你当然可以这样做:

printf("the origin's y coordinate is %f\n", point3_get_origin()->y);

该函数返回给定类型的值,因此只要表达式中需要这样的值,就可以使用函数的调用。

答案 3 :(得分:1)

你的意思是这样吗?

typedef void (*CALLBACK)(void);

CALLBACK getCallback();

void test()
{
    getCallback()();
}

在GCC 4.6.1(默认标准版)中编译没有警告。

答案 4 :(得分:0)

回答这个问题要比在这里发布更快更容易:尝试一下。

#include <stdio.h>

struct s {
        int a;
} s;

struct s * getS() {
        s.a = 13;
        return &s;
}

int main(int argc, char * const argv[]) {
        printf("%d\n", getS()->a);
        return 0;
}
% gcc test.c -o test -Wall -pedantic
% ./test
13
%

与迂腐警告不同。预期产出。看起来很完美。但是,正如已经指出的那样,最好存储返回值并检查错误。