C++言語における配列ポインタとポインタ配列の徹底的な分析(シリーズ一)


最近、フォーラムでは空港で配列ポインタとポインタ配列に関する議論がよく見られる.これはc++などの言語を学ぶ上で欠かせないステップです.
しかし、従来の指針のものは役に立ちますが、使いにくいものなので、勉強するのも簡単ではありません.近ごろ私も
何もすることができないので、勝手に書いた自分でこれらの方面の理解について、同業者の参考に供して、同時に自分を
の誤った理解が太陽の光にさらされ、みんなの評価を受けた洗礼を受けた.
file://Powered By ZosaTapo
file://[email protected]
################################
#                              #
#基本的な知識#
#                              #
################################
もちろん私たちはすべて最も簡単な内装タイプから始めて、最後に私はいくつかの普及をします.
まず基本的な形式を見て、私たちはここからスタートします!
-----------------------------------------------------
int a=10;
int *p=&a;
----------ポインタのポインタ--------
int b=20;
int *p=&b;
int **p2p=&p;
----------単純配列----------
int c[10];//10個の整数要素を含む整数配列
file://つまり各要素は整数です
         
------------------ポインタ配列-------------------------
int *p[10];//10個のポインタ要素を含むポインタ配列
file://つまり、各要素はポインタです
           
----------------------------------------------------------------------
int (*p)[10];//配列ポインタ、このポインタは
file://10要素を含む整数配列
上記の簡単な形式は私たちがまず理解しなければならないことであり、これは基本的な知識である.
同時に、c++言語の面で重要な知識のヒントを得る必要があります.
変数宣言の部分については、接尾辞結合変数の優先度が接頭辞よりも高い.
上の例の最後の2つを見ると,配列ポインタの
声明は私たちが変えなければならない.我々は()を用いて優先度の変更を実現し,実現した.
配列ポインタの宣言.
################################
#                              #
#さらに知識を高める#
#                              #
################################
配列、配列のポインタ、ポインタの配列、概念が多すぎます.私は概念をたくさん受け入れます.
その時、私はこれらの複雑なものを簡単にしたいと思っています.私は怠け者なので、概念が簡略化されています.
覚えたほうが簡単です.これらの概念の本質を認識しなければなりません
これにより概念を簡略化し、記憶の難易度を減らすことができる.
まずプログラムを見てください.

#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
 int vInt=10;
 int arr[2]={10,20};
 
 int *p=&vInt;
 int **p2p=&p;
 
 int *parr[2]={&vInt,&vInt};
 int (*p2arr)[2]=&arr;

 cout<<"Declaration [int vInt=10] type=="<<typeid(vInt).name()<<endl;
 cout<<"Declaration [arr[2]={10,20}] type=="<<typeid(arr).name()<<endl;
 cout<<"Declaration [int *p=&vInt] type=="<<typeid(p).name()<<endl;
 cout<<"Declaration [int **p2p=&p] type=="<<typeid(p2p).name()<<endl;
 cout<<"Declaration [int *parr[2]={&vInt,&vInt}] type=="<<typeid(parr).name()<<endl;
 cout<<"Declaration [int (*p2arr)[2]=&arr] type=="<<typeid(p2arr).name()<<endl;

 return 0;
}

実行結果は以下の通りです:(行番号XXを前に付けました)
#01 Declaration [int vInt=10] type==int
#02 Declaration [arr[2]={10,20}] type==int *
#03 Declaration [int *p=&vInt] type==int *
#04 Declaration [int **p2p=&p] type==int * *
#05 Declaration [int *parr[2]={&vInt,&vInt}] type==int **
#06 Declaration [int (*p2arr)[2]=&arr] type==int (*)[2]
結果を分析してみましょう.私たちはすでに第1部の基本的な知識を持っているので、私たちは今
私たちが宣言したタイプを明確に区別することができます.ここには主に2つの重要な部分がありますが、私たちは
事柄について話し、コンパイラがどのように実現するかの原理はここで議論されていない.
------#02:配列---------
今#02を見て、何か考えましたか?コンパイラから見れば、配列は対応するタイプのポインタタイプにすぎません.
配列を関数に渡すとポインタが渡されるので
パラメータを使用して配列要素を変更します.この変換はコンパイラが自動的に完了します.
void f(int[]);
int a[2]={10,20};
f(a);//この行はコンパイラが完了した関数変換f(int*p)に等しい
つまりコンパイラはint[]タイプからint*への変換を自動的に完了し、
コンパイラが完成したことに注意して、言語そのものが実現したと言ってもいいでしょう.
これには受け取る分しかない.
------#05:ポインタ配列----------
ポインタ配列のコンパイラ内部表示も対応するタイプのポインタです.
-------#06:配列ポインタ----------
配列ポインタのコンパイラ内部表示は少し特別です.
コンパイラ(あるいは言語自体)には配列ポインタという内部表現があります.
c++言語のタイプが厳格にチェックされている言語(もちろん暗黙的なタイプ変換があるものもあります)
だから私たちの次の書き方はコンパイルできません.
{
file://---------コンパイルはパスできません----------
int arr[3]={10,20};//3つの要素配列に注意
int (*p2arr)[2]=&arr;//注意2つの要素配列を指すポインタ
file://---------コンパイルはパスできません----------
}
################################
#                              #
#初歩的なまとめ#
#                              #
################################
上の2つのセクションの内容を通じて、皆さんは基本的に理解しているはずです.
配列、ポインタ、ポインタ配列、配列ポインタはいったいどうなっているのだろうか.
--------補充開始-----------------
配列とポインタの変換、およびポインタ(++,--)などを使用して配列を操作することについて、
配列に基づいてメモリに連続的に分布します.
しかし、私たちが「反復器」を使うとき、状況は違います.
この問題は本文では論じない.
--------補足終了----------------------
しかし、c++言語自体には奇妙な点がたくさんあります(c++はc言語や古いc++バージョンと互換性があることを考慮しなければならないからです).
組み込みタイプのこれらの性質の特徴は関数部分に着くと少し変化しますが、コンパイラを理解したら
何があっても、あなたはあまりおかしくありません.しかし、関数部分の内容についてはまたお話しします.
今、上の内容に戻ります.ここではやはり内装のタイプについてお話しします.明らかに同じタイプの変数は互いに値を割り当てることができる.
しかし、タイプの広がり、クラスの継承システムの問題など、他にも可能な場合があります.
もちろん、異なるタイプは一般的に互いに値を与えることができません.もちろん、ここの例外は強制転化です.
クラスの継承システムなどの状況が発生しました.
ここを見ると、次のプログラムがなぜ実行されているのかがわかります.
ここでも以下の手順を今日の内容のまとめとしています.

#include <iostream>
using namespace std;
int main()
{
 int a[2]={10,20};
 int *p=a;//      ,        ,         
 
 int vInt=10;
 int *parr[2]={&vInt,&vInt}; 
 int **p2p=parr;//    ,    
 
 return 0;
}

-----------------関数ポインタ部分は次回に書きます--------------------------------
原文住所:
http://blog.csdn.net/zosatapo/