【C/C++】指针使用中容易混淆的知识点总结

有学者认为指针是C和C++的精髓,记得当时老师说这种说法言过其实,换成“重要”一词来讲课,指针在C和C++中的地位可见一斑。后来博主用Java多了,渐渐对指针陌生了很多,于是查阅整理了一下笔记。这里对其严格的概念不作赘述,主要是列举一些例子方便理解。
【指针与数组】
指针通俗来讲就是地址。因此,下面的程序中函数demo1和demo2是等价的,把数组作为参数,实际上是把数组的地址作为参数,数组名代表的是数组的地址,也就是数组第一个元素的地址,p[i]和*(p+i)是等价的,当i=0,即有p[0]=*p。对于语句int p[7];在编译阶段编译器就已经知道数组的大小,因此sizeof(p)得到的是28,即数组p占空间为28字节(数组长度为7个整型数据,一个整型数据占4字节)。当把数组当参数传递,编译器会把它当做指针(并不是把整个数组空间传进去),在函数里执行sizeof(p)得到的是该指针变量的空间大小,指针变量在32位机上一般占4字节。
#include<iostream>
void demo1(int p[])
{
std::cout <<“参数int p[]的sizeof(p)为”<< sizeof(p) << std::endl;;
}
void demo2(int * p)
{
std::cout << “参数int* p的sizeof(p)为” << sizeof(p) << std::endl;;
}
int main()
{
int a[7] = { 1, 2, 3, 4, 5, 6, 7 };
std::cout << “数组a的sizeof(a)为” << sizeof(a) << std::endl;
demo1(a);
demo2(a);
std::cout << “a[0]的值为” << a[0] << std::endl;
std::cout << “*a的值为” << *a << std::endl;
system(“pause”);
return 0;
}
上面程序输出为:
数组a的sizeof(a)为28
参数int p[]的sizeof(p)为4
参数int* p的sizeof(p)为4
a[0]的值为1
*a的值为1

使用指针作为形数传递数组是常用的方法,一般需要另外加一个参数指明数组的长度,例如:
void fun(int *a,int size_of_a);
int * p[10];
fun(p,10);//或者 fun(p,sizeof(p)/sizeof(int));
【*与[]的优先级】
[]比*优先级高,*是自右至左结合。
因此,语句
int *p[5];
p与[5]先结合,其实就是int*( p[5]);显然是一个数组,数组元素是指向int类型的指针变量。
指向指针的指针:
int **p;
按照自右至左结合就可以理解成int (*(*p));这里(*p)是指向int类型的指针,所以p是指向int类型指针的指针。同样int ***p也能按照同样的方法分析。
【指向函数的指针变量和返回指针值得函数的区别】
int *fun(int x);
int (*fun)(int x);
对于int *fun(int x);根据优先级可以看作是int * (fun(int x)); 这里函数名是fun,有一个整型参数,函数返回值是指向整型的指针。
对于int (*fun)(int x);这里fun是指向函数的指针变量,函数有一个整型参数,函数返回值是整型,这时候括号是必需的。
指向函数的指针的一个用处是把函数作为参数传递。
例如:
#include<iostream>
void fun1(int i){
std::cout <<“执行fun1,传进参数i的值为:”<< i << std::endl;
};
void fun2(int j, void(*p)(int)){
std::cout << “执行fun2,传进参数j的值为:”<<j << std::endl;
std::cout << “在fun2里调用通过参数传进来的函数:p(j);” <<std::endl;
p(j);
}
int main()
{
fun2(3, fun1);//注意,fun1的参数只能通过fun2的参数传进去
system(“pause”);
return 0;
}
输出结果为:
执行fun2,传进参数j的值为:3
在fun2里调用通过参数传进来的函数:p(j);
执行fun1,传进参数i的值为:3
【指向数组的指针和指针数组的区别】

指针数组是数组元素为指针变量的数组,例如:

int *p[10];//即int *(p[10]);

指向数组的指针就是存放数组地址的指针变量,例如
int a[3] = { 1, 2, 3 };
int(*p)[3]=&a;
std::cout << (*p)[1] << std::endl;//输出2,注意不能写成*p[1]
std::cout << a[1] << std::endl;//与上面语句等价

 

=========添加内容分割线2016-4-3 21:59:51======

【const指针】
1、 指向常量的指针
不能通过指针改变它所指向对象的值
例如:
int a=5;
const int *p=&a;
*p=6;//非法
a=6;//合法
2、 常指针
指针变量的指向不能更改。
例如:
int a=1,b=2;
int * const p=&a;
p=&b;//非法
3、 指向常量的常指针
int a=1,b=2;
const int* const p=&a;
p=&b;//非法
*p=5;//非法

总结:只要记住*与其它运算符的优先级和结合顺序,就能逐步逐步分析,也可以最大限度地添加括号方便理解,不必记住每一种形式。
【2016-3-29】

发表评论

电子邮件地址不会被公开。 必填项已用*标注