1

C (89/90) で関数呼び出しをチェーンできるかどうか、およびC 仕様のどこで定義されているか疑問に思っていました。Google検索で言及されていないため、これは不可能だと思います。

私がこれについて考えたのは、友人との関連する会話で、構造体を返す関数が与えられた場合、同じステートメント内でその構造体に対して操作を実行できないと彼が言ったからです。代わりに、関数の結果を変数に代入し、関数の結果自体から直接ではなく、変数を介して構造体を操作する必要があります。これにより、関数をチェーンすることもできないと思いますが、仕様で説明されているこれらの制限を見つけることができないようです。

編集:申し訳ありませんが、戻り値について具体的に説明する必要がありました。関数が関数ポインタを返すと仮定すると、流暢な方法で、同じステートメント内で逆参照して結果を呼び出すことは可能ですか?

たとえばgetFunc、関数ポインタを返すと仮定します:

(*getFunc(getFuncParam))(otherFuncParam)

または、この場合、と呼ばれるメンバーを持つ をstruct想定します。structintcount

funcReturnsStruct(param).count++
4

5 に答える 5

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;
}

実際に見てください

于 2012-05-07T14:40:33.377 に答える
3

私の友人は、構造体を返す関数が与えられた場合、同じステートメント内でその構造体に対して操作を実行できないと私に言いました

関数の戻り値が代入のターゲットになることはできないという意味で、あなたの友人は正しいです (左辺値ではありません)。IOW、次のようなことはできません

int foo(void) { int x = 5; return x; }
...
foo() = 6;

ただし、関数の戻り値の型が構造体または共用体の場合は、次のようにコンポーネント選択演算子を戻り値に適用できます。

int x = foo().memb;

同様に、関数の戻り値の型が構造体または共用体へのポインターである場合、次のように記述できます。

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とにかく意味がありません。ステートメントが終了すると、 によって返される値の有効期間が終了するためです。変更された値を取得することはできません。

于 2012-05-07T15:56:05.750 に答える
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);

関数は指定された型の値を返すため、式でそのような値が必要な場合はいつでも関数の呼び出しを使用できます。

于 2012-05-07T14:56:42.340 に答える
1

このような意味ですか?

typedef void (*CALLBACK)(void);

CALLBACK getCallback();

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

GCC 4.6.1(デフォルトの標準)では警告なしでコンパイルされます。

于 2012-05-07T14:46:41.550 に答える
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
%

衒学的な警告ほどではありません。期待される出力。まったく問題ないようです。ただ、ご指摘のとおり、戻り値を格納してエラーチェックをしたほうがよいでしょう。

于 2012-05-07T14:56:22.433 に答える