今天看到了谭浩强的C语言第八章的指针,是我们以后使用得最多的一样工具,也是最让人畏惧的东西。其实对于指针,我们不要感到有一种高不可攀的感觉,我们可以将它细化到小模块的知识点。比如就我今天看的,我觉得我对指针的理解比刚开始的懵懵懂懂好多了,现在对于一些指针方面的知识感到很明了。
1.从最基本的谈起,一个最简单的关于指针的知识。定义一个指针变量。如
#include <iostream>
using namespace std;
int main()
{
int ival=3 ;
int *ptr ;
ptr = &ival;
cout<< *ptr <<endl;
return 0;
}
指针变量是用来存储变量地址,通过指针变量,可以找到我们要的变量的地址,然后通过地址找到地址内存的内容。其中我们要注意的一点是定义指针变量时一定要加上基类型,因为不同类型的元素所占的空间大小不同,如指针变量p指向一个整形数组,这执行p+1时,内存空间加了 4 Bytes 。如果指向一个 char类型,则执行p+1时,内存空间只加了 1 Bytes。2.对于二维数组,我们也可以定义指针变量
#include <iostream>
using namespace std;
int main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int *p;
p=a[0];
for(int i=0;i!=6;i++)
{
cout<<*(p+i)<<" ";
}
return 0;
}
运行结果: 1 2 3 4 5 6 ;
指针变量 p 为第零行 第零列的地址。
可能你看完上面的程序觉得很简单,不就是那样吗!错了,接下来我将要将二维数组中让人迷惑的知识点列举出来。
首先,关于二维数组名 a 和 a[0],&a[0][0] 是相同的吗?它们之间有什么区别呢 ?
我的回答是,a 和 a[0],&a[0][0]都是代表二维数组首元素的地址,不过他们并不完全相同。a 代表的是行地址,如果执行 a+1,a将指向下一行元素。而a[0]与&a[0][0]是相同的,它们都是指向列地址,当它们执行加1操作时,如a[0]+1,&a[0][0]+1,它们指向的将是同一行中的下一个元素。上面就是一个示例。p=&a[0][0],这样可以将元素逐一的输出。而如果将a赋给p,即 p=a ,系统会报错。这时候该怎么办呢,我们得定义一个指向一维数组的指针变量 int (*p)[n],其中n为二维数组每一行的元素数。这时可以这样赋值:p=a;然后可以这样输出数组中的元素。for(int i=0; i!=n;i++)
for(int j=0;j!=m;j++)
{
cout<<*(*(p+i)+j)<<" ";
}
这样也可以将数组元素全部输出。其中int (*p)[n]中的()不可以省略,因为[]的优先级比*高。以下是一个关于指针变量作参数的示例。#include <iostream>
using namespace std;
int main()
{
void average ( float *p , int n );
void search ( float (*p)[4], int n );
float score[3][4]={{51,52,53,84},{84,95,96,99},{57,98,59,54}};
average(*score,12);
search(score,2);
return 0;
}
void average (float *p,int n)
{
float *p_end;
float sum=0,aver;
p_end = p+n-1;
for(;p<=p_end;p++)
sum=sum+(*p);
aver=sum/n;
cout<<"aver="<<aver<<endl;
}
void search(float (*p)[4],int n)
{
for(int j=0;j<3;j++)
{
int flag=0;
for (int i=0;i<4;i++)
{
cout<<*(*(p+j)+i)<<" ";
if(*(*(p+j)+i)<60)
flag++;
}
cout<<endl;
if (flag>=2)
{
cout<<"有两门以上不及格";
}
cout<<endl;
}
}
3.今天看到的另一个知识点是关于函数指针。函数指针给我们使用相同样式的函数提供了方便。
int func(int x,int y)
定义函数指针的格式: int (*p)(int ,int );
使用指向函数的指针之前要将要使用的函数的函数名赋给 p: p=fun;#include <iostream>
using namespace std;
int max( int ,int );
int min( int ,int );
int add( int ,int );
int main()
{
int (*p)(int ,int );
int ival, jval,nval;
cin>>ival>>jval;
cin>>nval;
if(nval==1)
p=max;
else if(nval==2)
p=min;
else if(nval==3)
p=add;
int zval=(*p)(ival,jval);
cout<<zval<<endl;
return 0;
}
int max(int x,int y)
{
return x>y?x:y;
}
int min(int x,int y)
{
return x<y?x:y;
}
int add(int x,int y)
{
return x+y;
}
上面是一个典型的使用函数指针的例子。4.关于字符数组指针,今天看到了有几个重点。
(1).字符数组的初始化和字符数组指针的初始化有一点不同。
char str[14]="hello";
char *str1="hello";
char str[14]; str="hello"; //错误的初始化方法
char *str; str="hello"; //正确
(2).char str[14]; scanf("%s",str); //正确
char *str ; scanf("%s",str); //会产生警告,甚至会报错。会破坏数据。
今天的收获不止这些,可是语言表达能力不强,上述总结可能总结的优点乱,见谅。