これを読んでいるほぼすべての人が、Cに関する次の3つの重要な事実に精通していることでしょう。
[]
は、配列の場合と同様に、ポインターに対しても同様に機能します。これらの3つの事実は、Cでの配列とポインターの処理の絶対的な中心です。それらは、1つの中心概念の相互リンクされた側面です。この概念を適切に理解しないと、かなり基本的なCプログラミングを適切に行うことはできません。
今日の私の質問は、単純に、この概念の名前は何ですか?
私は昔ながらだと思っていましたが、私はいつも「Cの配列とポインターの等価性」、または略して「配列/ポインターの等価性」と呼んでいました。しかし、私はあなたがSOでそれらの言葉をほとんど話すことができないことを学びました。彼らはほとんどタブーです。
これは抽象的な質問や哲学的な質問のように思えるかもしれないので、より具体的にフレーム化するために、私が探しているのは、文で使用できる単純な名詞または名詞フレーズです。 この質問 に対する答えとして、「ポインター演算の構文糖として」。
(ただし、私はnotであることに注意してください。または、「Word 'equivalent'の何が問題になっていますか?」という質問への回答を探しています。ええ、私は知っています、それは学習者を誤解させて配列とポインタがなんとなく同じであると想像させることができます。 this FAQ list entry =。)
- 「配列添え字」演算子[]は、配列の場合と同様に、ポインターに対しても同様に機能します。
いいえ、実際には ポインターに対してのみ機能します 。式に_[]
_と入力すると、常に最初の要素へのポインターを取得します。 _arr[i]
_は*(arr + i)
と同等でなければならないため、これは必ず発生します。前者は後者の「構文糖」です。
- 配列のように見える関数パラメーターは、実際にポインターを宣言します。
これは実際には「配列調整」と呼ばれる特別なケースであり、コンパイラは暗黙的に配列型の関数パラメーターの宣言を最初の要素へのポインターに変更します。論理的根拠は確かに関数を式の「配列減衰」と互換性があるようにすることですが、C規格は用語を分離しています。
式と関数パラメーターの両方の場合は、多くの場合非公式に「配列減衰」と呼ばれます。ただし、これは式にのみ使用され、関数パラメータには使用されない場合があります。この用語の単一で一貫した使用は存在しないと思います。 「配列減衰」は私が思う最高の方法ですが、C規格ではその用語をどこにも使用していません。
(配列がポインターに変わることはあるが、その逆はできないため、「同等」という用語は嫌いです。実際、「配列とポインターは同じものです」などの混乱した信念を思いつく無数の初心者が常に存在します。同等」はまったく役に立ちません。)
C標準には、このための単一のWordはありません。 6.3.2.1p3の動作(1)を定義するときは「変換」、6.5.2.1p2の動作(2)を定義するときは「同等」、6.7.6.3p7で動作(3)を定義するときは「調整」を使用します。
私は古臭く、(1)が発生する式または(3)が発生する関数宣言について話していることをコンテキストで明確にしている限り、この「配列/ポインターの等価性」の呼び出しに問題はないと思います。ただし、「同等」が気に入らない人にとっては、「配列からポインタへの変換」という言葉がより口に合うと思います。これは、(1)のときに最も混乱することが多いからです。
array decayの用語を使用します。この用語は、それが示唆するものとよく合います。 Cの標準はこの文脈ではそれについて述べておらず、はい、私が標準で検索するために行った用語を聞いた最初の日、それを見つけることができませんでした(だから、誰が用語を造ったのかなどについて少し混乱しています)。また、)「ほとんどのシナリオの配列がポインターに変換される」ために書き込むこともできます...(-いいえ、これは単一名詞。しかし、これは誤解を生じさせません。標準自体はそれを「変換」と言います。
ほとんどの場合、私はそれを長いこと言ってから、Word( "array decaying")を括弧に入れようとします。実際、私はそれさえ言及せず、標準の言葉であるconversion to pointerで答えただけです。
「配列からポインターへの減衰」は合理的な速記であるとお勧めします。「減衰」は型変換の一般的な専門用語であり、C FAQの他の場所で先例があります: Question 6.12 :
Q:配列参照はポインターに減衰するため、arrが配列の場合、arrと&arrの違いは何ですか?
これを含む「崩壊」の拡張された技術的意味は、C++ 11以降のC++標準ライブラリの命名法に採用されています。 std::decay
言及された3つの概念に与えられた単一の名前はありませんが、少なくとも「現代」のCを記述する場合、それらを「同等」のいずれかの種類を暗示する記述は逆効果であると思います。 C99は、配列の減衰によって生成されたポインターが、他の手段で達成されたポインターと同じように動作する必要がないことを指定しています。与えられた:
char fetch_byte_at(void *p, int x) { return ((char*)p)[x]; }
struct {char arr[5][7];} s;
char test1(int x) { return s.arr[0][x]; }
char test2(int x) { return fetch_byte_at(&s, x); }
規格は、s.arr[0]
で使用されるポインター値test1
が((char*)(void*)s)
がfetch_byte_at
から呼び出されたときに使用されるポインター値test2
と同等ではない理由を直接指定しません。 ] _。ただし、test2
がs
のすべてのバイトを読み取ることができることを同時に意味します[x
の値が少なくとも34まで予測どおりに動作することを意味します] s.arr[0][x]
は、x
の値が6までの場合にのみ意味があると言います。
標準では、最初の2つのポイントを個別に矛盾させるものはありませんが、両方を保持することはできません。配列の減衰の結果は、配列の最初の要素への「通常の」ポインター以外のものであるか、配列に[]
演算子を適用すると、ポインターに適用するのとは異なる意味を持ちます。 #1と#2のどちらがC99によって無効にされたのかは不明ですが、現代のCではこれらが一緒になって「同等」を形成することはありません。
従来のCと「現代の」Cの違いを認識している場合、前者を便利にする用語の用語を確立すると役立つ場合があります。しかし、そのようなことはあなたが言及したポイントを超えています。残念なことに、私はそのようなものの標準用語を知りません。また、関連する概念をサポートしなくなったとき、そのような用語を提供する標準を探しません。
みんな、ありがとう。私はこの「答え」を使って、人々が出した答えとそれらに対する私の評価を要約します。適切な答えとしてではなく、誰かが賛成するなどを期待しています。
多くの人々がこの質問に真剣に考えを入れており、私はそれを感謝しています。しかし、現時点で私が結論付けられる唯一のことは、少なくとも今日、私が念頭に置いていた質問に対する答えがないということです。
かなりの数の人々が「アレイ減衰」を提案し、それは非常にナイスショットですが、それは私にとってはうまくいきません。元の質問にリストされているファクト1とファクト3を主に参照しますが、実際はファクト2ではありません。「はい、配列の減衰のため、配列の添字付けはポインター演算の構文シュガーと考えることができます。」 (または、少なくとも、意図が明確で有益なものであると言うことはできません。)「はい、配列の減衰とポインター演算が次のように定義される方法のために」と言う必要があります。それは、配列の添字付けはポインター演算の構文糖衣と考えることができます。
はっきりとは言いませんでしたが、標準で実際に使用されている単語を含むという要件はありませんでしたが、一般的で広く受け入れられている用語を探していました。そして、誰もがそのような用語をせき止めなかったことを考えると、誰もがある程度の憶測と「What about ...?」に従事していたことを考えると、関連するトリオの背後にある概念に広く使用されている単一の用語はないと結論付けます事実。 (除外されている「同等」以外。)
多数の回答者と解説者がこれをさまざまな方法で言っています(1つの回答はありません)。私は先に進んで、それに基づいてランディンの答えを受け入れます。他の人がそれを一番気に入っているようだからです。
私は今後、「Cの配列とポインターの対応」を使用してみて、うまくいくかどうかを確認します。配列とポインターは男性と女性のように異なり、実際にはかなり離れていますが、頻繁に文字を交換します。 :-)
これは抽象的な質問や哲学的な質問のように思えるかもしれないので、より具体的にまとめると、私が探しているのは単純な名詞または名詞句です。「はい、_____のため、配列サブスクリプションはこの質問に答えて.
探しているフレーズは「はい、配列サブスクライブは内部でポインター演算であるため、配列サブスクライブはポインター演算の構文シュガーと考えることができます」です。
もちろん、これは愚かなことです。なぜなら、配列のサブスクライブはポインター演算の構文糖衣であると言う理由は、それがまさにそれであるからです。あなたがこれを言っている人が、配列のサブスクライブ」、「ポインター算術」または「構文糖」の意味。これは、コンパイラーが2つの違いを知らないということではありません(その結果として得られるすべての構文シュガーの原因はコンパイラーにあるためです)。
この同じ質問は、より多くの低レベルの命令を使用することで自分でできる言語のすべてについて発生する可能性があり、使用される構文糖の量を変更するだけの複数の用語を使用してそれを参照することができます。全体のポイントは、それらが異なるようにふりをすることではなく(常に邪魔になりますが、それはポイントではありません)、プログラミングを簡単にすることです(ポインタ演算の構文糖として[]演算子を持たずにコードを書くことを考えてください。あなたはすぐにその存在の理由を理解します-それは異なるだからではなく、それは簡単だからです。
(しかし、私はその質問への答えや、「Word 'equivalent'の何が問題なのか?」という質問への答えを探しているのではないことに注意してください。同じFAQリストエントリ。)
あなたの質問は、「配列サブスクリプションがポインタ演算の単なる構文上の砂糖であるという意味での配列ポインタ等価性の現代用語は何ですか?」
答えは:
これは微妙な質問です。英語のシソーラスと辞書を見ると、用語similitudeがあなたのコンテキストに適しているかもしれないことがわかりました。
オックスフォードのオンライン辞書の定義では、Word Similar
は次のように定義されています。
外観、性格、または量が似ているが、同一ではない。
そして、Word Similitude
として:
何かに似ている品質または状態。
配列とポインターは同一ではありませんが、ときどき同様に扱われるため、次のように言います。
はい、配列/ポインターsimilitudeのため、配列の添え字は、ポインター演算の構文シュガーと考えることができます。
「ポインター/配列の等価性」または「ポインターへの」「配列減衰」などの用語は不正確であり、非常に誤解を招く可能性があることに同意します。
私は以下を提案します:
配列へのアクセス []演算子を使用withインデックスhas同等のポインター算術式。ただし、ポインターと配列の間に等価性はありません。多分個別の反復カウンターを保存するために、ポインターの値(コンテンツ)を喜んで変更できますが、「減衰」配列ではできません。不変であり、いくつかの点でC++参照と同様の動作を示します。
英語の動詞「減衰する」と「変換する」は、常に原文が変更されることを伝えます。配列名を使用するか、単項演算子「&」を使用しても、オペランドは変更されません。
したがって、「ポインターを生成する」または「ポインターを作成する」などの式はより正確になります。どちらの場合も、結果のポインターは一時的なものであり、(通常)CPUのGPレジスタに存在するという事実に反映されます、割り当てられません。
少なくともそれは私の理解ですが、分解を見るとそれが確認できるようです。
標準では、converted toという用語が使用されます。 配列とポインタの等価性は、arraydecayto pointersよりも優れています。標準ではこの用語はどこにも言及していませんが、配列とポインターのコンテキストでは、配列とポインターの等価と考えられるというプログラマー間の相互理解にすぎません。そして、ポインターと配列の等価性が意味するものは: ポインター算術演算と配列インデックス[それ]はCでは同等であり、ポインターと配列は異なります。 。