- ベストアンサー
関数から構造体を返す一般的な手法は
たとえば下のような平面上の点を表す構造体があって、 typedef struct { const int x; const int y; } Point; 2点間の中心を計算する関数を書くとします。 この場合、計算結果をどのように返せばよいでしょうか。 「ただ動けばよい」コードを書くことはできるのですが、 私が知りたいのは、どのような書き方が一般的かということです。 構造体の要素が const なので、 下のコードはコンパイルできません。 void center(Point* result, Point* p1, Point* p2) { result->x = (p1->x + p2->x) / 2; result->y = (p1->y + p2->y) / 2; } 新しいオブジェクトを作ってコピーする? void center(Point* result, Point* p1, Point* p2) { Point p = { (p1->x + p2->x) / 2, (p1->y + p2->y) / 2 }; memcpy(result, &p, sizeof(Point)); } この例のような小さい構造体であれば、 オブジェクトをまるごとリターンしてもよい? Point center(Point* p1, Point* p2) { Point p = { (p1->x + p2->x) / 2, (p1->y + p2->y) / 2 }; return p; } あるいは、そもそも構造体の要素を const にする手法は C言語では一般的でないのでしょうか? どうかご教授願います。
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
> あるいは、そもそも構造体の要素を const にする手法は > C言語では一般的でないのでしょうか? 一般的ではありませんし、今回の用途では、const修飾があるとまずいと思います。 > Point p = { (p1->x + p2->x) / 2, (p1->y + p2->y) / 2 }; このような書き方は本来できません。 集成体(配列および構造体)の初期化子には、定数式しか与えることができないからです。 処理系の独自拡張機能で、定数式以外を初期化子に使える場合もありますが、少なくともそれを期待するのは「一般的」ではありません。
その他の回答 (3)
- mac_res
- ベストアンサー率36% (568/1571)
一般的かどうかより、実際使うときに不自由ではないでしょうか?たとえばこんな風に遣うと思う例を書いてみました。constになってたら使えません。 -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- #include <stdio.h> typedef struct { double x; double y; } Point; void center(Point *result, Point *p1, Point *p2) { result->x = (p1->x + p2->x) / 2; result->y = (p1->y + p2->y) / 2; } void ent_p(Point *p) { char buf[BUFSIZ]; while (1) { fprintf(stderr,"enter x y >> "); fgets(buf, BUFSIZ, stdin); if (sscanf(buf, "%lf %lf", &p->x, &p->y) == 2) { return; } fprintf(stderr,"入力しなおし\n"); } } int main(void) { Point p1, p2, result; fprintf(stderr,"p1 "); ent_p(&p1); fprintf(stderr,"p2 "); ent_p(&p2); center(&result, &p1, &p2); printf("center = (%lg,%lg)\n", result.x, result.y); return 0; }
お礼
回答ありがとうございます。 サンプルコードまで書いていただいてどうも。 やはり const を外して、 計算結果を格納する場所へのポインタを 引数として渡すのがベストでしょうか。
- Tacosan
- ベストアンサー率23% (3656/15482)
ISO C なら Point center(const Point *p1, const Point *p2) { return (Point){ (p1->x + p2->x)/2, (p1->y + p2->y)/2 }; } でいけそうな気がする.
お礼
回答ありがとうございます。 そういう書き方もあるんですね。 勉強になりました。 これも構造体をまるごとリターンするやり方ですね。
- ggaogg
- ベストアンサー率43% (38/88)
こんなのどうでしょう? ちょっと変数名とかわかりにくいかもしれませんが、即席なので、すみません。 見るとわかると思いますが、構造体を戻り地にして、main関数での宣言時に代入しています。 #include <stdio.h> typedef struct tags{ const int a; const int b; } THESTRUCT; THESTRUCT result(THESTRUCT tag) { return tag; } int main() { THESTRUCT tagA = {4,5}; THESTRUCT tagB = result(tagA); printf("%d\n%d\n", tagB.a, tagB.b); return 0; } プロでもなんでもない者のたわごとです。
お礼
回答ありがとうございます。 ポインタ経由でなく構造体全体をリターンする方法ですね。 このやり方もアリなんでしょうか。
お礼
回答ありがとうございます。 調べてみたところ、 たしかに構造体は定数でしか初期化できないようですね。 構造体を変数で初期化するコードは、 私の環境ではコンパイルできたのでOKだと思っていましたが、 独自拡張だったみたいです。