”関数の仮引数の宣言”は”変数の宣言・定義”と同じように”宣言”と明確に考えるべきなのか”関数の仮引数”を”式”と考えて良いのかという問題です。
私が迷ってしまったのは"配列を仮引数"にとった例です。
規則として
”int a[ ] が int *a と同じ意味になるのは、唯一、関数の仮引数の宣言のばあいだけである”という規則がありますが、これは”関数の仮引数の宣言”は変数の宣言・定義”と同じように”宣言”と明確に考えている例だとおもいます。
int a[ ] が int *a と型名 変数名(引数名)と宣言の形をとっているので当然だと思いますが、一方
配列は、式の中で「先頭へのポインタ」によみかえられる。
↓
関数の引数は式なので、配列は「先頭へのポインタ」に読み変えられる←引数部分を”宣言”ではなく”式”と捉えてる←ここが私の迷っているところ
↓
よって、関数に渡ってくるのは、結局はつねにポインタだ。
という説明もあります。
私の今までの理解ではc言語では”宣言の部分”と”式”の部分は明確に区別されるものと考えていました。”宣言部分の初期化の="と”代入の=”とは明確に区別されていました。
それと同じように”関数の仮引数の宣言”は”宣言部分”と捕らえるのか”式”ととらえるのか
”宣言”と”式”が私の頭の中混乱しています。
宜しくお願いします。
No.4ベストアンサー
- 回答日時:
a[] 自体、という記述を見て、疑問点が分かったように思います。
[] は変数型の一部と見るべきなので、変数にあたるのは a[] ではなく a なのだと考えてください。
a は変数ですからこれ自体は式に間違いありません。今回の場合には int へのポインタ型の変数 a ということですね。
void Func(int ai[]) {} を例として考えてみます。
変数型に名前をつける typedef をご存知であろうと思いますが、これを使って上記関数の引数の型に ai_type(名前は任意ですが)という名前をつけるとすると、
typedef int ai_type[];
と書けますね。この型名を使って上記の関数は次のように書けます。
void Func(ai_type ai) {}
このように書くと、ai が変数であり、[] は変数型 ai_type の一部なのだということが納得できると思いますが、いかがですか。
上記のような観点で見ると、a[] は式と考えて良いかという質問は、「変数型」と「変数の識別子」の組み合わせは式ですかというのに近く、例えば int c は式ですかというのに近いので、これは式とはいえないということになります。
c は式ですが、int c は式ではないですよね。
同様に a は式ですが a[] は式ではなく、しかもこの場合の [] は ai_type という型を構成する要素である、ということになります。
私の再質問のご回答の最初で”a[] 自体、という記述を見て、疑問点が分かったように思います。”とあり、それに対し、詳しく説明していただき、疑問点は良く理解できました。大変有難うございました。
No.3
- 回答日時:
たぶん誤解されることは無いと思うのですが、ANo.002 で、「式というと 1*2+3 も式ですが、関数定義として void Func(1*2+3) {} はありえませんから少なくとも関数の"""仮引数は式とは言えないですね"""。
」と書きましたが、この意味は、関数の仮引数部分に任意の式を書くことはできないという意味であり、void Func(int* pi) {} の仮引数 pi 自体はもちろん式と言えますので、念のため。この回答への補足
1.void Func(int* pi) の仮引数 pi 自体
2.void Func(int a[ ])の仮引数a[ ]自体
1 2のpi 自体 a[ ]自体は式と考えてよいのでしょうか。
そこが私の疑問点の核心ですので補足を投稿しました。
宜しく願います。
No.2
- 回答日時:
式というと 1*2+3 も式ですが、関数定義として void Func(1*2+3) {} はありえませんから少なくとも関数の仮引数は式とは言えないですね。
関数のプロトタイプ宣言、例えば void Func(int*); の引数は、引数型を宣言しているだけなので、宣言でしょう。
関数の定義、例えば void Func(int* pi) {} の引数は、引数型が決まると同時に、引数(=変数)の実体ができるという意味で、定義でしょう。
問題の配列の場合ですが、関数のプロトタイプ宣言の void Func(int ai[]); と void Func(int* pi); は全く同じ意味になると思います。
関数のプロトタイプ宣言の引数の名前は省略できるので、上記は void Func(int[]); と void Func(int*); と書いても良いわけです。
これらはどちらも、引数は int を指すポインタだと言っていることになります。
関数の定義では、引数を本体内部で使うのならば名前が必要なので、引数並びに ai とか pi とかいう名前が必要になります。
上記のように、配列を関数に値渡しする場合には、引数は配列の先頭アドレスで初期されれたポインタが渡ります。
引数の実体がポインタなので、この場合、配列の大きさは無視されるわけですね。
なので、 void Func(int ai[3]); の 3 は書く必要は無くて、void Func(int ai[]); で事足りるわけです。
「関数に渡ってくるのは、結局はつねにポインタだ。」というのは、上記のような意味で正しいわけですね。
以上は、配列の値渡しの場合でしたが、C++ では配列の参照渡しもできて、この場合には関数のプロトタイプは void Func(int (&)[3]); のようになります。3 は省略できません。
関数定義では void Func(int (&ai)[3]) {} のようになります。
配列の参照渡しで関数に引数として渡るのは、元の配列の別名(上記例では ai)です。
良く理解してほしいのですが、配列の先頭アドレスとか、ポインタとかが渡るのではなく、元の配列をアクセスするための代理の名前が渡るという感じです。
例えば main() { int aiOriginal[3]; Func(aiOriginal); } のように配列を渡して、これを void Func(int (&aiAnotherName)[3]) { ... } で受けた場合、
aiAnotherName は aiOriginal の別名なので、aiAnotherName で配列の内容を弄ると、aiOriginal そのものを弄ることになります。
ここには、ポインタが云々という発想は全く無く、元の配列を別名で弄るということなのです。
No.1
- 回答日時:
>関数の引数は式なので、配列は「先頭へのポインタ」に読み変えられる
これは仮引数の宣言の話ではなくて、
int func(int a[]);
なる関数を実際に呼び出す際に
int x[] = {1, 2, 3};
func(x);
でその引数 x が式だから先頭へのポインタと解釈される、ということじゃないのかな。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
配列の要素数に変数を入れたい...
-
関数から配列を返すには?
-
構造体のextern方法
-
define で 配列
-
C#でのフィボナッチ数列
-
C#で配列が空かを判定するには?
-
C言語において、 配列要素をひ...
-
背景差分法における正規化距離
-
AfxBeginThread の引数について
-
C言語の穴埋め問題です
-
C言語について質問です。
-
Cのエラー
-
MFCのCArrayを使った二次元配列
-
[C++]const int と配列
-
Cプログラムについて
-
C言語 数値の連続入力について
-
5人分の氏名と英語、国語、数...
-
int i, int i[1];
-
c言語
-
VBのByte配列をVARIANTに格納し...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
c言語
-
c言語プログラミング 等差数列...
-
define で 配列
-
構造体のextern方法
-
C#で構造体の配列を持った構造...
-
C言語において、 配列要素をひ...
-
MFC - ダイアログボックスのPic...
-
C言語の2次元配列 容量が大き...
-
2次元配列のマスを数える方法...
-
C言語 ファイルの指定された行...
-
Cのエラー
-
コンボボックスでデフォルト値...
-
C#で配列が空かを判定するには?
-
C#でのフィボナッチ数列
-
ポインタを使って構造体の配列...
-
C言語の課題が出たのですが自力...
-
MFCのCArrayを使った二次元配列
-
C言語の配列のコピーについて
おすすめ情報