正如前一篇博客所说的,但俗人都是急于求成和有慵懒的,都不喜爱花时间去阅览那些咱们以为单调的文字描绘,喜爱直接进入主题。可是有时分恰恰便是因为咱们的这种急于求成和慵懒,使得咱们绕了很大一个弯,到最后仍是回到了文字描绘上来,所以我觉得恰当的文字描绘下,让读者关于文章的全体有个大约的知道之后,再去学习能收成更好的作用。我的前两篇关于C指针的博客用的摘要都是copy我第一篇C指针博客的摘要,当然这篇也不破例,仍是会引证我第一篇博客的摘要,仅仅在引证摘要之前我要先告知件事儿,便是关于函数指针和指针函数、以及指针常量和常量指针我就不在此解说了,有爱好的朋友能够参阅我之前写的两篇博客—C言语的那些小秘密之函数指针和C言语的那些小秘密之const修饰符。
懂得C言语的人都知道,C言语之所以强壮,以及其自由性,绝大部分表现在其灵敏的指针运用上。因而,说指针是c言语的魂灵,一点都不为过。所以从我的标题加了个(一)也能够看出指针的重要性,我尽或许的向咱们告知清楚我关于指针的了解。所以在解说的过程中我尽或许的用代码加文字的描绘办法,经过代码的剖析来加深咱们关于指针的了解,我给出的都是完好的代码,所以读者能够在看的过程中直接copy下去即可运转,期望下面的解说能够对你有所协助。
先让咱们来看看一段十分了解的代码:
#include
void main(int argc,char *argv[])
{
while(argc–>1)
printf("%s\t",*++argv);
}
运转成果如下:
或许仍是有人不是很了解main函数里的参数argc和argv是什么意思,在此做一简略的解说,argc为命令行输入的参数个数,在此argc=3,有三个参数,分别是:fdsa.exe fdsa asdf,argv是一个指针数组,在此相当于char *argv[0]="fdsa.exe"、char *argv[1]="fdsa"、char *argv[0]="asdf"。有了上面的解说信任能够很好的了解main函数的参数了。
现在来剖析下上面的代码,程序中有一句argv++;可是咱们上面的剖析是argv是一个数组名,而数组名是不能进行这样的++运算的,莫非犯错了嘛?!可是分明运转成果现已就在眼前了,在解说之前咱们再来看如下一段代码:
#include
void main()
{
char *argv[]={"this","is","shuzu"};
*++argv;
}
编译发现犯错了。
好了现在咱们能够来解说为什么会呈现如上两种状况了,有种特殊状况便是数组名作为函数参数,传递的是数组的首地址,体系会把形参当作变量来处理,所以假如咱们吧main函数改写为main(int argc,char **argv);就好了解多了。
看了上面的代码,接下来咱们看看指针数组和数组指针的差异地点。
一、指针数组指的是一个数组,数组中的每个元素都是指针类型,一切的指针都指向不同的地址,所指的地址的数据也不一定相同,可是所指的数据类型有必要相同。
二、数组指针指的是界说的是一个指针,而指针指向的是数组,指针指向数组首单元的地址,关于数组内部元素的特点不了解,仅仅是规则了数组首单元的地址,经过它能够找到整个数组。
接下来看看一段代码:
#include
void main()
{
int *p=new int [10];
int arr[10];
int (*ptr)[10];
for(int i=0;i<9;i++)
{
arr[i]=i;
printf("a[%d]=%d\t%d\t",i,arr[i],&arr[i]);
}
printf("\n");
int j=0;
ptr=&arr;
printf("\nptr=%d\t&arr=%d\t&arr[0]=%d\n",ptr,&arr,&arr[0]);
printf("\n");
for(;j<9;j++)
{
printf("ptr%d=%d\t%d\t",j,*((*ptr)+j),&(*ptr)[j]);
}
printf("\n");
}
运转成果如下:
在程序中咱们打印了数组a中每个数组元素的值和其相应的地址,一起也界说了一个数组指针,int (*ptr)[10]; ,在引证数组指针的过程中有必要要注意的是数组指针的维数有必要要引证的数组维数相同,否从会犯错。咱们能够把int (*ptr)[10]; 拆开来看,把指针ptr看成是指向int [10];的类型,把int [10]视为一种新的类型,所以在运用指针ptr的时分类型有必要要一起,即有必要是一个int [10]这样的数组。
对以上的代码稍加修正:
#include
void main()
{
int arr[4][4];
int (*ptr)[4];
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
arr[i][j]=i*j;
printf("a[%d]=%d\t%d\t",i,arr[i][j],&arr[i][j]);
}
printf("\n");
}
printf("\n");
int j=0;
ptr=arr;
printf("\nptr=%d\t&arr=%d\t&arr[0]=%d\t&arr[0][0]=%d\n",ptr,&arr,&arr[0],&arr[0][0]);
printf("\n");
for(;j<16;j++)
{
if(j%4==0&&j!=0)
printf("\n");
printf("ptr%d=%d\t%d\t",j,*((*ptr)+j),&(*ptr)[j]);
}
printf("\n");
}
运转成果如下:
或许有的读者看了int arr[4][4];int (*ptr)[4]; 这两句代码之后以为接下来的代码ptr=arr;有错,因为arr是一个二位数组,而ptr仅仅一个指向int [4]类型的指针。可是要注意了,从运转成果咱们也能够必定的是上面的代码是正确的,可是为什么是正确的呢?!首要咱们把arr分为两部分来看,第一部分为int [4],第二部分为arr[4],这样就一望而知了,咱们能够以为咱们界说了一个一维数组arr[4],数组有四个元素,每个元素的类型为int [4],因而和一般的数组相同,咱们能够将该数组名赋给指针,其实也便是第一个元素的地址交给指针。即: ptr=arr;或许ptr=&arr[0]。其他状况以此类推。
下面再来看看一段代码:
#include
void sum(int s[])
{
int i;
printf("%d\n",s);
printf("%d\n",*(s+3));
printf("%d\n",&s);
printf("%d\n",*s++);
printf("%d\n",*s++);
printf("%d\n",*s++);
printf("%d\n",*s);
printf("\n");
}
void main(int argc,char *argv[])
{
int ss[4];
for(int i=0;i<4;i++)
ss[i]=i;
sum(ss);
printf("%d\n",ss);
printf("%d\n",&ss);
}
运转成果如下:
在main函数中咱们运用了两句 printf("%d\n",ss);和 printf("%d\n",&ss);来打印数组ss的地址,值得注意的便是数组的首地址的几种表明办法,还能够是&ss[0];在调用ss函数的过程中,咱们运用的是数组作为参数,一起为了加深读者关于数组作为参数的时分能够运用++这样的操作符形象,我在此运用s++的办法打印了整个数组。仔细的读者会发现我运用的 printf("%d\n",s);和 printf("%d\n",&s);在此打印的成果不再相同了,跟在main函数顶用这样的句子打印数组首地址的成果一起不符合,这也从旁边面阐明了当数组名作为参数的时分,体系是将它作为变量处理的,所以打印的成果不一起。
指针的解说到此就告一段落了,因为自己水平有限,博客中的不当或过错之处在所难免,殷切期望读者批评指正。一起也欢迎读者一起讨论相关的内容,假如愿意沟通的话请留下你名贵的定见。