指针就像Java中的引用概念一样,使用地址指引程序找到内存中的数据,绕来绕去还是有点晕的,不过多打印几次,查查资料,思考一下也能想通。
指针变量
指针变量在内存中存放的是地址,在编译系统中占4个字节,指针变量定义方法为:
#include <stdio.h>
int main(){
int a=100;
int *p;
p=&a;//取址
printf("%d\n",p);//地址
printf("%d\n",*p);//地址指向的值
return 0;
}
[*]符号表示该变量为指针变量,在打印的时候,无符号则会打印出变量存储的地址数据,加上星号会打印出对应地址的数据,此刻的星号表示取值,[&]符号表示取址,使用指针则可以间接访问数据。
指针数组
指针是左值,可以被修改,数组名是地址常量,不可以被修改,指针数组定义方法为:
#include <stdio.h>
int main(){
int a=100;
int b=200;
int c=300;
int *pp[3]={&a,&b,&c};//指针数组,存储元素为地址
for (int i = 0; i < 3; ++i) {
printf("%d\n",pp[i]);//地址
printf("%d\n",*pp[i]);//数据
}
return 0;
}
其中指针数组存储的每个元素都为指向整形变量的指针,即为[int *],所以打印结果为:
定义指针数组还可以写为:
int a[]={1,2,3};
int *p;
p=a;//方法1
p=&a[0];//方法2
由于数组名就是数组第一个元素的地址,即首地址,所以两种方法是一样的,但最好使用取址符号。
数组指针
数组指针是一个指针,指向一个数组,如:
#include <stdio.h>
int main(){
int temp[]={5,7,9};
int (*g)[3]=&temp;//数组指针
for (int l = 0; l < 3; ++l) {
printf("%d\n",g[l]);//地址
}
for (int m = 0; m < 3; ++m) {
printf("%d\n",*(*g+m));//数据
}
printf("%d %d %d",&temp,&temp[1],&temp[2]);
return 0;
}
打印结果为:
当指针变量g指向数组temp[]时,其实就是把数组名temp这个指针常量赋给了指针变量g,此时*g与temp是等价的,而不是g与temp等价,所以g[l]打印出的地址和temp[l]不一样,指针+1并不是地址上数值+1,而是根据类型指向下一个元素。
数组指针与二维数组
同Java一样,C语言也没有真正意义上的二维数组,是通过一个一维数组存放指向其他一维数组的元素扩展。
#include <stdio.h>
int main() {
int array[2][3] = {{0, 1, 2}, {3, 4, 5}};
int (*p)[3] = array;
printf("**(p+1): %d\n", **(p+1));
printf("**(array+1): %d\n", **(array+1));
printf("array[1][0]: %d\n", array[1][0]);
printf("*(*(p+1)+2): %d\n", *(*(p+1)+2));
printf("*(*(array+1)+2): %d\n", *(*(array+1)+2));
printf("array[1][2]: %d\n", array[1][2]);
return 0;
}
输出结果为:
这里指针指向二维数组的时候并没有使用&取址,数组名array表示首元素array[0]的地址,即int (*p)[3] = &array[0];
,相当于int (*p)[2][3]=&array;
即为:
#include <stdio.h>
int main() {
int array[][3] = {{0, 1, 2}, {3, 4, 5}};
int (*p)[2][3] = &array;
printf("**(p+1): %d\n", **(*p+1));
printf("**(array+1): %d\n", **(array+1));
printf("array[1][0]: %d\n", array[1][0]);
printf("*(*(p+1)+2): %d\n", *(*(*p+1)+2));
printf("*(*(array+1)+2): %d\n", *(*(array+1)+2));
printf("array[1][2]: %d\n", array[1][2]);
return 0;
}