C言叶のあれらの小さい秘密の【针(二)】
9672 ワード
FROM: http://blog.csdn.net/bigloomy/article/details/6612387
=======================================================
今ではどのブログにも要約が求められていますが、私がそのまま前の内容に続いて話し始めたら、初めて私のブログを見た人は私が何を言っているのか分からないかもしれませんので、前のブログの最初の段落を要約として引っ越しましょう.
C言語を知っている人は、C言語が強いのは、自由性のほとんどが柔軟なポインタの運用に現れていることを知っています.だから、ポインタはc言語の魂であり、少しも過言ではない.だから私のタイトルから(一)ポインタの重要性も分かるし、できるだけポインタに対する理解を皆さんにはっきり説明します.だから、説明の過程でできるだけコードと文字の説明方式を使って、コードの分析を通じて私たちのポインタに対する理解を深めて、私が与えたのはすべて完全なコードなので、読者は見る過程で直接copyを実行することができます.以下の説明があなたに役に立つことを望んでいます.
ここでも特に強調しますが、後で似たような状況が発生した場合、私のブログの最初の段落は要約として使用されます.前のブログで要約を見たことがある場合は、重複した要約部分をスキップして読まず、そのまま本文に入ることができます.
次に、前編のポインタ部分では、配列のポインタと配列を指すポインタ変数を見てみましょう.配列のポインタは配列の開始アドレスであり、配列要素のポインタは配列要素のアドレスである.配列要素の参照には、通常2つの方法が使用できます.
1、a[8]のように下付き法.
2、指針法.
ポインタ法を用いる利点は,ターゲットプログラムのメモリ占有量が少なく,実行速度が速く,品質が向上することである.なぜポインタがこのような利点を持っているのか、ここで説明する必要があると思います.ポインタは32ビットマシンの下で4バイトを占有しているため、関数がメモリを占有する大きなオブジェクト、例えばint a[2000]を伝送すると、ポインタ参照で伝送するのが簡単で、メモリを節約し、オブジェクトをコピーする時間も節約できます.インデックス法で配列を参照する場合は、配列の開始アドレスを取りに行き、base+offsetで直接アドレスに変換し、ポインタよりも多くの操作を行う必要があります.
以上から分かるように、ポインタの能力はとても強くて、多くの事を完成することができて、Cの精髄はポインタにあって、CがASMの効率に近づくことができます.したがって,プログラムを書く際にはポインタの利点を十分に利用し,効率的なC言語コードを書く必要がある.
コードを見てみましょう.
上のコードを書くとき、私は多くの注釈を加えて、説明文を印刷して、コードがあまり美しく見えませんが、コードの読み取りには少しも影響しません.次に、実行結果を見てから、位置合わせして分析しましょう.
上の写真は少し大きいかもしれません.画像はもっと効果的に見えるので、私はやはり画像を伝えながら印刷結果を以下のようにコピーしました.画像がネット上の理由で開けられない場合は、以下の運転結果を見てください.******************************************************************a[0]=0 a[1]=1 a[2]=2 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7*************************************************************************************************************************************
**********************************************************p 0=0 p 1=1 p 2=2 p 3=3 p 4=4 p 5=5 p 6=6 p 7=7**********************************************************************************************************
*************************************************************************a[0]=0 a[1]=1 a[2]=2 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7****************************************************************************************************************************************************************************************************************************************************************
***************************************************************************************0 1244944 0 1244948 0 1244952 0 1244956 0 1244960 1 1244964 2 1244968 3 1244972 0 1244976 2 1244980 4 1244984 6 1244988 0 1244992 3 1244996 6 1245000 9 1245004
****************************end end end******************************
*************2次元配列bのアドレスと、ppと*pppの値*************************
&b[0][0]=1244944 pp=1244944 *ppp=1244944
****************************end end end******************************
*************2次元配列b[0][0]、および*ppおよび*pppの値**********************
b[0][0]=0 *pp=0 **ppp=0
****************************end end end******************************
*****************************************************************************************************************************************************************************************************************************************************************************************
&pp=1244932 &ppp=1244928
ppp=1244932 *ppp=1245008 9 Press any key to continue
まず、私たちが使用している3つの1次元配列aを印刷する方法を見てみましょう.いずれもa配列の各要素を印刷することに成功しました.次のクラスは2次元配列bを印刷する過程で、配列bの各要素を印刷すると同時に、私たちもそれに対応するアドレスを印刷しました.注意深い読者はアドレス間の法則を送信することができます.私たちはint型を宣言しているからです.したがって、各要素は4バイトを占有し、隣接する要素間のアドレスの差は4である.
次に,ポインタppとポインタを指すポインタpppを用い,ポインタpppを使用する過程で特にその使用に注意した.文を印刷することによって、私たちは&b[0][0],pp,*pppを印刷しました.それはすべて同じ結果を持っていて、すべて2次元配列b[0][0]のアドレスなので、次に印刷するb[0][0],*pp,**pppはすべてb[0][0]の値で、次にポインタの方法で2次元数グループbの印刷に成功しました.
次にポインタpp、ダブルポインタpppのアドレスを印刷し、同時にpppと*pppの値も印刷しました.*pppの値と最後に印刷した配列要素のアドレスの関係に注意しました.なぜこのような結果になったのでしょうか.私たちは前にint**ppp=&ppを使ったからです.*pppとppは同じ記憶空間を指し、そのアドレスは&pp=1244932であるため、ppを変更する価値がある場合、*pppの値も変更に従う.だから注意深い読者は最後の印刷文printf("%dt",*(*ppp-1));で、二次元配列bの最後の最後の要素を正常に印刷するには、*(*ppp-1)を使用します.
2 Dポインタクラスを使用して配列を印刷する方法は、次のコードを参照してください.
#include
int main(){//************************************************************************//printf("*************************************************************");int b[4][4];for(int n=0;n<4;n++){for(int m=0;m<4;m+){b[n][m]=n*m;printf("%dt",b[n][m]);printf("%dt",&b[[n][m]); } printf(""); } printf("****************************end end end******************************"); //****************************end end end******************************// int *pp=&b[0][0]; int **ppp=&pp;
//************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************ for(*ppp;*ppp<(&b[0][0]+16);(*ppp)++) printf("%d\t",**ppp); printf("****************************end end end******************************"); //****************************end end end******************************//
return 0; }
実行結果は次のとおりです.
コードの中で私たちの赤いマークの部分に注意して、多くの人は2次元のポインタ*pppを採用して印刷する時最も間違いやすい地方を行って、多くの人は以下の方式を使用します:
for(*ppp;*ppp<(&b[0][0]+16);*ppp++)
問題はないようで、正しい結果が得られるようですが、よく分析すると問題点がわかります.++の優先度が*より高いので、まずppp++演算を行い、それから*pppです.そうすると、私たちが前に話した野指針の問題が発生します.だからprintf("%dt",**ppp);メモリエラーが発生します.したがって、ここではカッコ(*ppp)++を付ける必要があります.このように*pppの中のアドレスこそb[0][0]のアドレスであり、次に++操作とprintf("%dt"、**ppp");2 D配列bの要素を正常に印刷できます.
=======================================================
=======================================================
今ではどのブログにも要約が求められていますが、私がそのまま前の内容に続いて話し始めたら、初めて私のブログを見た人は私が何を言っているのか分からないかもしれませんので、前のブログの最初の段落を要約として引っ越しましょう.
C言語を知っている人は、C言語が強いのは、自由性のほとんどが柔軟なポインタの運用に現れていることを知っています.だから、ポインタはc言語の魂であり、少しも過言ではない.だから私のタイトルから(一)ポインタの重要性も分かるし、できるだけポインタに対する理解を皆さんにはっきり説明します.だから、説明の過程でできるだけコードと文字の説明方式を使って、コードの分析を通じて私たちのポインタに対する理解を深めて、私が与えたのはすべて完全なコードなので、読者は見る過程で直接copyを実行することができます.以下の説明があなたに役に立つことを望んでいます.
ここでも特に強調しますが、後で似たような状況が発生した場合、私のブログの最初の段落は要約として使用されます.前のブログで要約を見たことがある場合は、重複した要約部分をスキップして読まず、そのまま本文に入ることができます.
次に、前編のポインタ部分では、配列のポインタと配列を指すポインタ変数を見てみましょう.配列のポインタは配列の開始アドレスであり、配列要素のポインタは配列要素のアドレスである.配列要素の参照には、通常2つの方法が使用できます.
1、a[8]のように下付き法.
2、指針法.
ポインタ法を用いる利点は,ターゲットプログラムのメモリ占有量が少なく,実行速度が速く,品質が向上することである.なぜポインタがこのような利点を持っているのか、ここで説明する必要があると思います.ポインタは32ビットマシンの下で4バイトを占有しているため、関数がメモリを占有する大きなオブジェクト、例えばint a[2000]を伝送すると、ポインタ参照で伝送するのが簡単で、メモリを節約し、オブジェクトをコピーする時間も節約できます.インデックス法で配列を参照する場合は、配列の開始アドレスを取りに行き、base+offsetで直接アドレスに変換し、ポインタよりも多くの操作を行う必要があります.
以上から分かるように、ポインタの能力はとても強くて、多くの事を完成することができて、Cの精髄はポインタにあって、CがASMの効率に近づくことができます.したがって,プログラムを書く際にはポインタの利点を十分に利用し,効率的なC言語コードを書く必要がある.
コードを見てみましょう.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[8];
int *p;
//*************************** a **************************//
printf("
*************************** a **************************
");
for(int i=0;i<8;i++)
{
a[i]=i;
printf("a[%d]=%d\t",i,a[i]);
}
printf("
****************************end end end******************************
");
//****************************end end end******************************//
//*************************** **************************//
printf("
*************************** **************************
");
p=a;
for(int j=0;j<8;j++)
{
printf("p%d=%d\t",j,*p++);
}
printf("
****************************end end end******************************
");
//****************************end end end******************************//
printf("
");
//************************ *************************//
printf("
************************ *************************
");
for(int k=0;k<8;k++)
{
printf("a[%d]=%d\t",k,*(a+k));
}
printf("
****************************end end end******************************
");
//****************************end end end******************************//
//**************************** b ********************//
printf("
*************************** b *******************
");
int b[4][4];
for(int n=0;n<4;n++)
{
for(int m=0;m<4;m++)
{
b[n][m]=n*m;
printf("%d\t",b[n][m]);
printf("%d\t",&b[n][m]);
}
printf("
");
}
printf("
****************************end end end******************************
");
//****************************end end end******************************//
int *pp=&b[0][0];
int **ppp=&pp;
//********************* b 、 pp *ppp ****************//
printf("
********************* b 、 pp *ppp ****************
");
printf("
&b[0][0]=%d\tpp=%d\t*ppp=%d
",&b[0][0],pp,*ppp);
printf("
****************************end end end******************************
");
//****************************end end end******************************//
//***************** b[0][0]、 *pp **ppp ******************//
printf("
***************** b[0][0]、 *pp **ppp ******************
");
printf("
b[0][0]=%d\t*pp=%d\t**ppp=%d
",b[0][0],*pp,**ppp);
printf("
****************************end end end******************************
");
//****************************end end end******************************//
//*************************** **************************//
printf("
*************************** **************************
");
for(pp=&b[0][0];pp<(&b[0][0]+16);pp++)
printf("%d\t",*pp);
printf("
****************************end end end******************************
");
//****************************end end end******************************//
printf("
&pp=%d\t&ppp=%d
",&pp,&ppp);
printf("
ppp=%d\t*ppp=%d
",ppp,*ppp);
printf("%d\t",*(*ppp-1));
return 0;
}
上のコードを書くとき、私は多くの注釈を加えて、説明文を印刷して、コードがあまり美しく見えませんが、コードの読み取りには少しも影響しません.次に、実行結果を見てから、位置合わせして分析しましょう.
上の写真は少し大きいかもしれません.画像はもっと効果的に見えるので、私はやはり画像を伝えながら印刷結果を以下のようにコピーしました.画像がネット上の理由で開けられない場合は、以下の運転結果を見てください.******************************************************************a[0]=0 a[1]=1 a[2]=2 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7*************************************************************************************************************************************
**********************************************************p 0=0 p 1=1 p 2=2 p 3=3 p 4=4 p 5=5 p 6=6 p 7=7**********************************************************************************************************
*************************************************************************a[0]=0 a[1]=1 a[2]=2 a[3]=3 a[4]=4 a[5]=5 a[6]=6 a[7]=7****************************************************************************************************************************************************************************************************************************************************************
***************************************************************************************0 1244944 0 1244948 0 1244952 0 1244956 0 1244960 1 1244964 2 1244968 3 1244972 0 1244976 2 1244980 4 1244984 6 1244988 0 1244992 3 1244996 6 1245000 9 1245004
****************************end end end******************************
*************2次元配列bのアドレスと、ppと*pppの値*************************
&b[0][0]=1244944 pp=1244944 *ppp=1244944
****************************end end end******************************
*************2次元配列b[0][0]、および*ppおよび*pppの値**********************
b[0][0]=0 *pp=0 **ppp=0
****************************end end end******************************
*****************************************************************************************************************************************************************************************************************************************************************************************
&pp=1244932 &ppp=1244928
ppp=1244932 *ppp=1245008 9 Press any key to continue
まず、私たちが使用している3つの1次元配列aを印刷する方法を見てみましょう.いずれもa配列の各要素を印刷することに成功しました.次のクラスは2次元配列bを印刷する過程で、配列bの各要素を印刷すると同時に、私たちもそれに対応するアドレスを印刷しました.注意深い読者はアドレス間の法則を送信することができます.私たちはint型を宣言しているからです.したがって、各要素は4バイトを占有し、隣接する要素間のアドレスの差は4である.
次に,ポインタppとポインタを指すポインタpppを用い,ポインタpppを使用する過程で特にその使用に注意した.文を印刷することによって、私たちは&b[0][0],pp,*pppを印刷しました.それはすべて同じ結果を持っていて、すべて2次元配列b[0][0]のアドレスなので、次に印刷するb[0][0],*pp,**pppはすべてb[0][0]の値で、次にポインタの方法で2次元数グループbの印刷に成功しました.
次にポインタpp、ダブルポインタpppのアドレスを印刷し、同時にpppと*pppの値も印刷しました.*pppの値と最後に印刷した配列要素のアドレスの関係に注意しました.なぜこのような結果になったのでしょうか.私たちは前にint**ppp=&ppを使ったからです.*pppとppは同じ記憶空間を指し、そのアドレスは&pp=1244932であるため、ppを変更する価値がある場合、*pppの値も変更に従う.だから注意深い読者は最後の印刷文printf("%dt",*(*ppp-1));で、二次元配列bの最後の最後の要素を正常に印刷するには、*(*ppp-1)を使用します.
2 Dポインタクラスを使用して配列を印刷する方法は、次のコードを参照してください.
#include
int main(){//************************************************************************//printf("*************************************************************");int b[4][4];for(int n=0;n<4;n++){for(int m=0;m<4;m+){b[n][m]=n*m;printf("%dt",b[n][m]);printf("%dt",&b[[n][m]); } printf(""); } printf("****************************end end end******************************"); //****************************end end end******************************// int *pp=&b[0][0]; int **ppp=&pp;
//************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************ for(*ppp;*ppp<(&b[0][0]+16);(*ppp)++) printf("%d\t",**ppp); printf("****************************end end end******************************"); //****************************end end end******************************//
return 0; }
実行結果は次のとおりです.
コードの中で私たちの赤いマークの部分に注意して、多くの人は2次元のポインタ*pppを採用して印刷する時最も間違いやすい地方を行って、多くの人は以下の方式を使用します:
for(*ppp;*ppp<(&b[0][0]+16);*ppp++)
問題はないようで、正しい結果が得られるようですが、よく分析すると問題点がわかります.++の優先度が*より高いので、まずppp++演算を行い、それから*pppです.そうすると、私たちが前に話した野指針の問題が発生します.だからprintf("%dt",**ppp);メモリエラーが発生します.したがって、ここではカッコ(*ppp)++を付ける必要があります.このように*pppの中のアドレスこそb[0][0]のアドレスであり、次に++操作とprintf("%dt"、**ppp");2 D配列bの要素を正常に印刷できます.
=======================================================