プロが教える店舗&オフィスのセキュリティ対策術

#include <stdio.h>

void init_val(double *a, int n);

int main(void)
{
double x[6];
int i, n;

n = sizeof(x) / sizeof(x[0]); /* 配列の要素を求める */
init_val(x, n); /* 配列の初期化 */
printf("配列の要素数は%dです。",n);
printf("各配列の要素の中身は次の通りです。\n");
for( i = 0 ; i < n ; i++)
{
printf("x[%d]=%f\n", i, x[i]);
}

return 0;
}

void init_val(double *a, int n)
{
int i;

for( i = 0 ; i < n ; i++ )
{
a[i] = i * 0.123;
}
}

---------------------------------------------------------------------------------------------
配列の要素数は6です。各配列の要素の中身は次の通りです。
x[0]=0.000000
x[1]=0.123000
x[2]=0.246000
x[3]=0.369000
x[4]=0.492000
x[5]=0.615000

このプログラムの
n = sizeof(x) / sizeof(x[0]); /* 配列の要素を求める */

この部分が分かりません、
sizeof(x) は48
sizeof(x[0]) は8でした。

48を8で割って6という要素数を求めているわけですが、

このように設定してわざわざ、要素数を求める意味はあるのでしょうか?

A 回答 (6件)

配列の要素数を求める機能が C 言語に存在しない為です。



言語設計の時点では、要素数は固定長で指定するものなので、
要素数を求める機能など無駄だと思われていたのかもしれません。

ただそれでは不便なので...

処理系によっては、要素数を求めるマクロ関数が独自に用意されています。
https://msdn.microsoft.com/ja-jp/library/ms17577 …

C++ 言語ならば、
配列を array クラスで置き換れば、メンバー関数で一発です。
http://www.cplusplus.com/reference/array/array/s …
    • good
    • 0
この回答へのお礼

参考にさせて頂きます。
回答ありがとうございました。

お礼日時:2016/08/15 11:49

double x[6]と要素数は6つと定義しているわけですから、


n = sizeof(x) / sizeof(x[0]);
と、書かなくても n = 6 と書けばすむことです。
ただ、保守性の問題から、定数を直接至る所へ記述するのは良くないことです。
(要素数を変更する必要ができたときに修正箇所が少ない方がいいですよね)
#define ですますこともできますが、#define をかかなければなりません。
その点、定数(この場合6)を書いておくのではなく、sizeof(x) / sizeof(x[0]) にしておけば、要素数の定義(この場合 double x[6])を変更するのみでよくなります。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
参考にさせて頂きます。

お礼日時:2016/08/15 11:50

しいて言えば


sizeof(x) / sizeof(x[0]) は (x が配列なら) 必ず x の要素数を与える
くらいかな.

あと一応突っ込んでおくと sizeof は関数じゃないからね.
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
参考にさせて頂きます。

お礼日時:2016/08/15 11:50

> このように設定してわざわざ、要素数を求める意味はあるのでしょうか?



無いと言えば無いですよね(笑)。
例えば次のようにして書いたらわざわざsizeof使わなくても済みますし。

#include <stdio.h>

#define N 6 /* こういう風にしちゃう */

void init_val(double *a, int n);

int main(void)
{
 double x[N];
 int i;

 init_val(x, N); /* 配列の初期化 */
 printf("配列の要素数は%dです。", N);
 printf("各配列の要素の中身は次の通りです。\n");
 for( i = 0 ; i < N ; i++)
  {
   printf("x[%d]=%f\n", i, x[i]);
  }

 return 0;
}

void init_val(double *a, int n)
{
 int i;

 for( i = 0 ; i < n ; i++ )
  {
   a[i] = i * 0.123;
  }
}

つまり「こういう動作をさせたい」って動作結果だけを考えた場合、このコードでは必ずしもsizeofは必要ないです。
ただ、練習問題っつーか例示ですしねぇ・・・。必然じゃないにしても「sizeof」の動作を教える為には・・・と言うあくまで「例示」じゃないでしょうか。
    • good
    • 0
この回答へのお礼

参考にさせて頂きます。
回答ありがとうございます。

お礼日時:2016/08/15 11:49

>このように設定してわざわざ



設定? 意味不明です。

48は配列全体のサイズ(byte)
8は配列要素のサイズなので、
配列の要素数nは宣言の変更(要素の数や要素の型の変更)
に応じて「自動的」に変化します。

とても便利だと思いますが・・・
    • good
    • 0
この回答へのお礼

参考にさせて頂きます。
回答ありがとうございました。

お礼日時:2016/08/15 11:48

もし、そのようにしない場合は、要素数が6なので、


以降は、
n=6; の行を追加するか
for( i = 0 ; i < n ; i++) のところを
for( i = 0 ; i < 6 ; i++) のように書き直す必要があります。

その前提で、
もし、要素数を10にした場合は、
double x[10];のほかに
for( i = 0 ; i < 10 ; i++) のように書き直す必要があります。

つまり、n = sizeof(x) / sizeof(x[0]); /* 配列の要素を求める */
を行っていれば、変更は1っ箇所で済みます。
これは、個人だけでソースを管理している場合は、ありがたみが感じられませんが、
会社で開発する場合のように、複数の人が、同じソースをメンテナンスする場合は、
非常に有効な方法になります。

この方法をとらないで、
要素数を10にした場合、
double x[6];
for( i = 0 ; i < 6 ; i++) 
の2か所を変える必要がありますが、もし、for( i = 0 ; i < 6 ; i++) の場所が
非常に離れていた場合、ここの修正を見落とす可能性があります。

それに対して、n = sizeof(x) / sizeof(x[0]); /* 配列の要素を求める */
のようにしていれば、変更箇所は1か所だけなので、だれがメンテナンスしても
バグを誘発する危険がありません。

同じ思想で、6の代わりに
#define YOSO_SU (6)
と定義し、
double x[YOSO_SU];
for( i = 0 ; i < YOSO_SU; i++) 
のようにコーディングをする方法もあります。
これも変更箇所を1か所だけにするという意味では、非常によくつかわれてます。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
参考にさせて頂きます。

お礼日時:2016/08/15 11:47

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!