• ベストアンサー

関数から構造体を返す一般的な手法は

たとえば下のような平面上の点を表す構造体があって、 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言語では一般的でないのでしょうか? どうかご教授願います。

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.2

> あるいは、そもそも構造体の要素を const にする手法は > C言語では一般的でないのでしょうか? 一般的ではありませんし、今回の用途では、const修飾があるとまずいと思います。 > Point p = { (p1->x + p2->x) / 2, (p1->y + p2->y) / 2 }; このような書き方は本来できません。 集成体(配列および構造体)の初期化子には、定数式しか与えることができないからです。 処理系の独自拡張機能で、定数式以外を初期化子に使える場合もありますが、少なくともそれを期待するのは「一般的」ではありません。

Gishi
質問者

お礼

回答ありがとうございます。 調べてみたところ、 たしかに構造体は定数でしか初期化できないようですね。 構造体を変数で初期化するコードは、 私の環境ではコンパイルできたのでOKだと思っていましたが、 独自拡張だったみたいです。

その他の回答 (3)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.4

一般的かどうかより、実際使うときに不自由ではないでしょうか?たとえばこんな風に遣うと思う例を書いてみました。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; }

Gishi
質問者

お礼

回答ありがとうございます。 サンプルコードまで書いていただいてどうも。 やはり const を外して、 計算結果を格納する場所へのポインタを 引数として渡すのがベストでしょうか。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

ISO C なら Point center(const Point *p1, const Point *p2) { return (Point){ (p1->x + p2->x)/2, (p1->y + p2->y)/2 }; } でいけそうな気がする.

Gishi
質問者

お礼

回答ありがとうございます。 そういう書き方もあるんですね。 勉強になりました。 これも構造体をまるごとリターンするやり方ですね。

  • ggaogg
  • ベストアンサー率43% (38/88)
回答No.1

こんなのどうでしょう? ちょっと変数名とかわかりにくいかもしれませんが、即席なので、すみません。 見るとわかると思いますが、構造体を戻り地にして、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; } プロでもなんでもない者のたわごとです。

Gishi
質問者

お礼

回答ありがとうございます。 ポインタ経由でなく構造体全体をリターンする方法ですね。 このやり方もアリなんでしょうか。

関連するQ&A