• ベストアンサー

全配列に0を入力

c言語で配列を宣言した後に、ループを使わずに 配列全体に0を入力したいのですが、そのような方法はありますか。 あれば、どのようにすればよいか教えてください。お願いします。

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

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

整数であればmemsetで0を埋めればよいのですが、浮動小数点数やポインタの場合、内部表現が0とは限らないので、次のような関数を使えば一応ループを回避できます。 void fill(int *array, size_t n) {  if (n > 0)  {   *array = 0;   fill(array + 1, n - 1);  } } ここで、arrayの型は必要に応じて変更してください。 例えば、double型の配列ならdouble *arrayとしてください。 あるいは、もう一つの手として、あらかじめ全要素を0で初期化した配列を別に用意しておいてmemcpyでコピーするなら、どんな型でもOKです。

ashiato-li
質問者

お礼

回答ありがとうございます。 memsetでは計算したときに違った値を出してくるときがあったので助かりました。 回答ありがとうございました。

ashiato-li
質問者

補足

一応使えているのですがポインタの部分とsize_tの指定が、よく理解できないのでよければ、この文がどのように動いているのか解説してもらえないでしょうか。

その他の回答 (11)

回答No.12

配列として宣言しているデータ型にもよりますが、1バイトや2バイト単位のデータ型の場合は、以下のような方法でループ回数を減らし、多少パフォーマンスが向上する可能性もあります。 ループを使わない方法ではありませんので、ご参考までに。 例) char s[100]; long l = 0; long *p = (long*)s; for (l = 0; l < sizeof(s) / sizeof(long); l++){ *p++ = 0; }

ashiato-li
質問者

お礼

回答ありがとうございます。 速度を上げることも目標の1つだったので参考になりました。 ありがとうございます。

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

> ループを回避したいのは、ある程度ループが繰り替えされるとなぜか > プログラムが強制終了されてしまうからです。 ループを使わずに回避するのではなく、なぜ強制終了されるのか、その原因を究明することの方が先決だと思います。 問題のあるコードを補足していただければ、もっとまともな解決策が見つかるかもしれません。 なお、配列の0クリアは、(厳密には移植性がありませんが)memsetを使うのが現実解です。そのためには、環境を明らかにすべきです。

ashiato-li
質問者

お礼

回答ありがとうございます。 環境を書いておくべきでした。すみません。 環境は、 windows xp professional sp2 borland c++ compiler 5.5 CPad for borland c++ compiler です。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.10

「ループを使わない目的」はなんですか? 結局、トレードオフになるわけですが、 例えばANo.5のコードはループを再起呼出で置換してるものです。 一般に再起はループより理解しがたい(≒保守しにくい)といわれますし、 別に速度上の優位性があるわけでもないですし(劣るとも限りませんが)。 目的が「ループを使わないでかけるか」というパズル(知的遊戯)なら十分な解ですが、 C言語で再起処理にするメリットが考えにくいところです。 もしも速度に焦点があるなら、実行速度が確保できる可能性が高そうなのは多分、 > あるいは、もう一つの手として、あらかじめ全要素を0で > 初期化した配列を別に用意しておいてmemcpyでコピーする これじゃないですかね。 どの程度のメモリが要求されるかは配列サイズ次第ですが、 再起関数を書いてもコード領域は使いますし。

ashiato-li
質問者

補足

回答ありがとうございます。 ループを回避したいのは、ある程度ループが繰り替えされるとなぜか プログラムが強制終了されてしまうからです。 この原因が分かればループを使うのですが。

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

#5です。 > 一応使えているのですがポインタの部分とsize_tの指定が、よく理解できないのでよければ、この文がどのように動いているのか解説してもらえないでしょうか。 指定方法ですが、 int a[10]; fill(a, 10); とします。 動作ですが、再帰的にa[9], a[8], a[7], ..., a[0] に0を埋めているだけです。 ついでに、 > #8 構造体のメンバが配列だけの場合でも、サイズが同じになるかどうかは規格上保証されません。

ashiato-li
質問者

お礼

再度の回答ありがとうございます。 プログラムの動きを理解することができました。

  • colder
  • ベストアンサー率43% (30/69)
回答No.8

C99が使えるなら int x[10]; struct foo { int mem[10]; }; *(struct foo*)&x = (struct foo){0}; これなら、内部表現が非0の型でも平気。

  • MrBan
  • ベストアンサー率53% (331/615)
回答No.7

参考:(CでなくC++なら)標準にstd::fillがありますね。 (内部実装はループかも知れませんけど…これなら内部表現が非0でも平気) #include <algorithm> int array[128]; // 例 const std::size_t size = sizeof array/sizeof array[0]; std::fill(array, array + size, 0);

ashiato-li
質問者

お礼

回答ありがとうございます。 今回はcでお願いします。

  • om_unk
  • ベストアンサー率0% (0/1)
回答No.6

すいません。知識が乏しく、嘘をいってました。 インテルコンパイラの説明書リンクします。 ベクトル化って調べるとかなり不明なことが書かれていました。適当なこと言ってしまいました。 インテルコンパイラなら、インテルの言うところのベクトル化をしてくれます。 が正しいです。 インテルの言うところのベクトル化はURLを参考ください。 msnで適当に探したものなので、もしかしたら消えるかも。。

参考URL:
http://download.intel.com/jp/developer/jpdoc/ccomp40j.pdf
ashiato-li
質問者

お礼

再度の回答ありがとうございます。 ベクトル化については、URLを参照させていただきました。 まだ、理解しきれませんでしたがコンパイラによってはそのような機能があることを知れて勉強になりました。 ありがとうございます。

  • om_unk
  • ベストアンサー率0% (0/1)
回答No.4

いろいろでてますねー。 ループ使いたくないのは速度の問題です? いいコンパイラならベクトル化すればOKだと思いますよ。(配列を展開しとけばOK) コードが汚くみえるからやだ? アーキテクチャ依存のコードはやだ? では前の回答に従うのがいいですね。

ashiato-li
質問者

補足

回答ありがとうございます。 よければベクトル化するとはどういうことか、教えてもらえませんか。

回答No.3

int a[10]; memset(a, 0, sizeof(a)); こんな感じでいけます。定石なので覚えておいて損はないでしょう。

ashiato-li
質問者

お礼

回答ありがとうございます。 配列の中身を0にすることができました。 ありがとうございます。

回答No.2

配列宣言時の初期化子を指定すれば良いです。 例えばこんな感じです。 int i[10] = {0}; 構造体にも使用できます。

ashiato-li
質問者

補足

回答ありがとうございます。 ですが、宣言をした後の方法でお願いします。