c也学习了很久了,每次遇到指针就感觉用起来不顺手。现在整理一下。
声明并赋值:
int *p = 123;
说明: p 是一个指针类型的变量,它指向 int 类型。p 的值是一个内存地址,并且是整型变量的内存地址。
在变量声明时,* 用来标识 p 是一个指针。在变量使用时,* 用来提取变量的值。例如:
printf("%d", *p); // 此时的 *p 就表示值 123
printf("%d", p); // 此时的 p 就表示123 在内存中的地址
正式使用时,可能情况如下:
*p = 45;
或
int a = 23;
p = &a; // 此时,p 就表示为内存地址,不需要使用标识符 *。此表达式为指针的赋值运算。
或
int *pp;
pp = p; // 此表达式为指针间的相互赋值。此时,pp就指向了p所在的地址,也就是把 *p 的值付给了 *pp。
见下面的使用方式:
int a = 123, *p = &a;
说明:声明 int 类型的变量 a 和 int 类型的指针变量 p ,同时取 a 的地址赋值给 p。此时的 *p 没有提取内容的意思。
上面的举例中,指针变量的类型均为 int 类型。当然,也可以指向其它类型:char float double short struct enum long 等。
指针的本质为 内存地址,所以指针是可以进行加减运算的。多用在和 数组 相关的操作中。原因,数组在内存中占据连续的地址空间。在其它类型中,无意义。
int a[5], *p = a;
说明:数组名 表示数组的首地址,所以 a 就是 数组a 的首地址,而声明中 *p 的赋值操作,就让 p 指向了 数组的首地址。
也可以写成如下形式:
p = &a[0]; // [] 的优先级是高于 & 的,此表达式首先运算 a[0] ,然后运算 &,即&(a[0])。
数组的第二个元素地址:
int *pp;
pp = p + 1; // 数组在内存中的地址是连续的,指针操作会很方便。此表达式表示,指针指向的当前位置向前 (高位在前,低位在后) 移动一个位置 (数组中一个元素占据的长度,并不是值一个字节、一个位)。
或
pp = a + 1;
或
pp = &a[1];
另外一个例子:
char *c = "this is c language.";
说明:这里的赋值字符串,在内存中是以字符串数组的形式存在的;所以, char 型指针c,代表的是字符串数组的首地址。
指针 = 0,表示为空指针,不指向任何具体变量。指针在没有赋值时,值是任意的,不能使用,否则会造成意外。
同类型的指针是可以相互比较的。
pl == pr,表示两个指针指向同一个地址。
pl > pr,表示 pl 处于高位
pl < pr,表示 pr 处于高位
注意:
方括号和圆括号的优先级高于 * 和 &,但是方括号和圆括号的优先级是相同的。变量的阅读规则:从左向右,从里向外。
* 只是一个标志,与变量名为组合关系。
补充:
int **p, p 为指向另一个指针的变量,该指针指向一个整型变量。int *(*p);
int (*p)(), p 为指向函数的指针,而函数的返回类型为 int。*p -->() --> int。首先 p 是一个指针,其指向一个函数,返回值为 int 类型。
int *p(), p 为返回指针值的函数,该指针指向整型变量。p() --> * --> int。首先 p 是一个函数,其返回值为指针,并且是 int 类型的指针。
int *p[n],p 为指针数组,由 n 个指向整型变量的指针元素组成。p[n]--> * --> int。首先 p 是一个数组,其数组的元素类型为 int 型指针。
int (*p)[n],p 为指向整型二位数组的指针变量,二位数组的列数为 n。*p --> [] --> int。首先 p 是一个指针,在这里可以表示一个数组,指针的数组(数组的数组),就是二维数组,其位 int 类型。
c++的引用和指针
引用就是指对象本身
int m = 6;
int &n = m; n 是 m 的引用,其就表示m本身,对 n 的所有操作,就是对 m 的所有操作。在代码使用中,直接使用n。例如:
printf("%d", n); // 结果为 6
void func(int &x) {
x = x + 6;
}
....
func(m); // 引用代指对象本身,相当于传递了对象的指针,但是书写的时候却不是以指针的方式。执行完后,m值为 12
int *p = 6;
int &n = *p; // 引用只能初始化一次
printf("%d", n);