質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

4回答

1976閲覧

C言語で引数が何に使われているのかわからない部分があります

ababab

総合スコア47

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2015/01/12 13:04

C言語で、関数「reverse」の「num」がいつどこに使われているのかわかりません。

void reverse(int[], int);

int main(int argc, const char * argv[]) {
int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int i;

reverse(data, 10); for (i = 0; i < 10; i++) { printf("%d ", data[i]); } printf("\n"); return 0;

}

void reverse(int array[], int num) {
int i, tmp;
for(i = 0; i < num / 2; i++) {
tmp = array[i];
array[i] = array[num - 1 - i];
array[num - 1 - i] = tmp;
}
}

この場合、「void reverse(int array[], int num)」において、この関数内で使われているarray[]の値をmain内のdataに使っていますよね。
ですが「num」の値は、main内のどこで使われているのでしょうか...

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

numは配列のサイズを指定しているだけですので、mainでは使用していません。

また、配列はポインターを関数に渡しているので内容を書き換えることができますが、intは値をコピーして渡しているだけですので、読み取り専用になります。

投稿2015/01/12 13:29

argius

総合スコア9390

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ababab

2015/01/12 14:15

回答ありがとうございます。 つまり、関数の引数に配列を使う場合、「(int array[],」の次は配列の要素数を表すint型の変数を書かなければならないということでしょうか?
argius

2015/01/12 14:21

C言語では、配列のサイズをarrayから知ることができませんので、それを渡す必要があります。 順番は後でなくてもかまいません。例えば、main関数では、配列のサイズargcが先に来ていますね。
guest

0

例えば、

lang

1int sum(int, int); 2 3int main(){ 4 printf("%d\n",sum(10,20)); 5} 6 7int sum(int x, int y){ 8 return x+y; 9}

というプログラムがあったときに、sumの中のxymainのどこで使われているのか疑問に持ちますか?持たないとすれば、質問文の、

ですが「num」の値は、main内のどこで使われているのでしょうか...

というのが的外れだとわかると思います。

また、

この場合、「void reverse(int array[], int num)」において、この関数内で使われているarray[]の値をmain内のdataに使っていますよね。

も、やや表現がおかしく、正しく書き直すと、

この場合、「void reverse(int array[], int num)」において、main関数内のdataを、この関数内でarray[]という名前で参照していますよね。

です。
さらに書くと、

この場合、「void reverse(int array[], int num)」において、main関数内の10を、この関数内でnumという名前で参照していますよね。

というのが、numについての説明となります。

蛇足ですが、他の方の指摘のように、main関数中ででてくる配列サイズを数字を直接書くのは良くない。
普通は、

lang

1int main(int argc, const char * argv[]) { 2 int data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 3 int i; 4 5 reverse(data, sizeof data/sizeof data[0]); 6 for (i = 0; i < sizeof data/sizeof data[0]; i++) { 7 printf("%d ", data[i]); 8 } 9 printf("\n"); 10 return 0; 11}

のように、sizeof演算子を使うと思います。これはコンパイル時に計算されるので、10と書いたのと実行コードは同じになります。プログラムのどこにも配列サイズを書く必要が無い。
煩雑な書き方だと思えば、

lang

1#define array_size(var) (sizeof var/sizeof var[0])

のように、マクロを定義してarray_size(data)と使うことも出来ます。

投稿2015/01/12 15:58

otn

総合スコア84557

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

c言語において、配列の要素数を配列変数から取得することはできないのでそのような仕様になるのだと思います。
例として

lang

1 int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 2

という配列変数があるとして、変数dataが要素数10の配列だと証明するもの変数dataにはありません。

lang

1void reverse(int array[], int num) { 2 int i, tmp; 3 for(i = 0; i < num / 2; i++) { 4 tmp = array[i]; 5 array[i] = array[num - 1 - i]; 6 array[num - 1 - i] = tmp; 7 } 8}

上記reverse関数では、第一引数のint array[]の要素の並びを入れ替える処理を行いますが、そのためにはarray[]の要素数がわからないといけません。
しかしarray[]からは要素数を取得できないので引数を追加して要素数を指定するような仕様になります。
また、reverse関数に指定する第二引数が実際の要素数と違う場合には配列として確保したメモリ以外の部分を参照してしまうので、想定しない動きをします。(配列の要素ではない値を取得したり、プログラムが落ちるなど)

>>int array[]の次に出てきたものは配列の要素数になると言う解釈でよろしいでしょうか?
上記の解釈ではなく、reverse関数においては、第一引数int array[]の次、第二引数のint numには要素数が指定されることを前提にしているということです。
第二引数のint numに指定される値が間違いなくint array[]の要素数であるというのはreverse関数の使用者が保障しなくてはいけません。

以上です。
参考になれば幸いです。

投稿2015/02/11 14:50

MiyukiAizawa

総合スコア41

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

お邪魔します。

lang

1int main(int argc, const char * argv[]) { 2* int data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 3 int i; 4 5* reverse(data, 10); 6* for (i = 0; i < 10; i++) { 7 printf("%d ", data[i]); 8 } 9 printf("\n"); 10 return 0; 11}

上記でアスタリスク(*)をつけた行で、10という数値が配列dataの要素数として使用されていますね。
本来これはマジックナンバーなので、定数として宣言すべきで

lang

1int main(int argc, const char * argv[]) { 2 const int DATA_LENGTH = 10; 3 int data[DATA_LENGTH] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; 4 int i; 5 6 reverse(data, DATA_LENGTH); 7 for (i = 0; i < DATA_LENGTH; i++) { 8 printf("%d ", data[i]); 9 } 10 printf("\n"); 11 return 0; 12} 13 14void reverse(int array[], int num) { 15 int i, tmp; 16 for(i = 0; i < num / 2; i++) { 17 tmp = array[i]; 18 array[i] = array[num - 1 - i]; 19 array[num - 1 - i] = tmp; 20 } 21}

のようにするのがよい慣習とされています。
reverse関数を呼び出すとき、二つ目の引数にDATA_LENGTH(=10)を渡しているので、reverse関数内部ではnumが10になります。(他の回答者さんの回答が正確で、10をコピーして渡しています)
このようにすれば、少しはわかりやすくなったのではないでしょうか?

以上です。
参考になれば幸いです。

投稿2015/01/12 13:50

ShinpeiYamamoto

総合スコア540

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ababab

2015/01/12 14:11

回答ありがとうございます。 void reverse..のint array[]の次に出てきたものは配列の要素数になると言う解釈でよろしいでしょうか? 仮に関数reverse内で他にint型の変数を使う場合、 (int array[], int num2, int num)とした場合は、arrayの要素数はnum2になるということでよろしいでしょうか? 初歩的な質問で申し訳有りません
ShinpeiYamamoto

2015/01/12 14:23

その様にreverse関数の引数を宣言して内部の実装を変更しなければ、numが配列の要素数として使用されます。(reverse関数内部ではnumという名前を配列の要素数として使用しているからです) なので、渡す側もreverse(data, ???, DATA_LENGTH)というように渡さなければいけません。 また、num2を配列の要素数として渡すよう変更するのであれば、reverse関数の中身のnumとなっている部分をすべて、num2に変更した上で、新たに追加した引数numを使用するコードを追加します。 ①引数に渡す側が記述している順番で、関数には値(やポインタ)が渡される。 ②関数内のコードでは、引数として宣言している名前で値(やポインタ)を受け取り使用することができる。 ということになります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問