C语言指针详解
// 举例说明:
// 代码:
#include<stdio.h>
int main() {
// 定义一个指针变量(没有赋值):
int *p; // '*' 是指针变量的标识符!表明某一变量是指针变量。
// 定义一个整型数组变量:
int array[]= {5,10,15};
// 指针变量的赋值只能用同类型的变量的地址进行赋值:
p=array; // 数组名,就是数组的第一个元素所在的地址! 即array==&array[0]。
printf("已知条件: int *p; array[]= {5,10,15}; p=array;\n\n");
// 输出指针p的地址。
printf("&p \t\t: %d\n",&p);
// 输出指针p所保存的地址,因为指针变量,存储的是某一变量的地址!
printf("p \t\t: %d\n",p);
// 输出数组array的地址。
printf("array \t\t: %d\n",array);
// 输出数组array第一个元素的地址,注意由于array[0]的类型为整型,所以获取地址要加取址符'&'
printf("&array[0] \t: %d\n",&array[0]);
// 输出数组array第二个元素的地址。
printf("&array[1] \t: %d\n",&array[1]);
// 输出指针p所指向的元素的值!'*' 该符号表示获取内存地址中所存储的值!
printf("*p \t\t: %d\n",*p);
// 输出数组array的地址中所保存的值!
printf("*array \t\t: %d\n",*array);
// 输出数组array第二个元素的地址中所保存的值!
printf("*(&array[1]) \t: %d\n",*(&array[1]));
// 输出指针地址自增一后的地址!
printf("++p \t\t: %d\n",++p);
// 输出指针p所指向的元素的值!'*' 该符号表示获取内存地址中所存储的值!
printf("*p \t\t: %d\n",*p); // 由于p中的地址自增一,因此此时p指向数组第二个元素
// 输出指针地址自增一后的地址中所存放的值!
printf("*(++p) \t\t: %d\n",*(++p)); // 先是p是中的地址自增一,然后再是去地址中存放的值
// 输出数组array第三个元素值!
printf("array[2] \t: %d\n",array[2]);
return 0;
}
输出结果:
注意事项:
- 指针地址的类型为长整型,因此有的编译器运行上述代码时,对于"%d"可能会报错,需要改成"%ld"。
- const char *p=“Hello world!” 是可行的,因为常量字符串的赋值给指针变量时,赋值的值其实是字符串变量的首地址,而非字符串变量本身!
- const int *p=5 是不可行的,因为整型变量的赋值,赋值的值本身不是地址,而是整型变量的值!
- 其他注意事项如下图所示:
输出结果:
其他:
- 01、通过指针来读取数据
#include <stdio.h>
int main() {
int x;
int *px = &x;
scanf("%d",px);
printf("%d",x);
return 0;
}
- 02、如果指针不指向任何有意义的内存地址或变量,赋值为NULL
int *q = NULL;
- 03、*和&互为相反即:(*&x)就是x。
- 04、通过强制类型转换完成不同类型指针间的相互赋值
int a;char b;
int *pa;char *pb;
pa=(int*)&b;
pb=(char*)pa;
- 05、用sizeof()获取变量占据的内存单元数
float array[20];
printf("%d\n",sizeof(array)); //将输出4*20=80
- 06、对于数组a来说,a 和 &a[0] 的值相同,都是数组0号元素地址,*a 等同于a[0],&a是数组地址,值和上两者一样,但意义不同!
- 07、对于指向数组a的指针p来说,可以通过*(p+2)或者p[2]来访问数组a的第三元素,如:
#include <stdio.h>
int main() {
int a[5]={1,2,3,4,5};
int *p=a;
printf("*(p+2): %d\n",*(p+2));
printf("p[2]: %d\n",p[2]);
return 0;
}
- 08、元素地址 = 数组起始地址 + sizeof(element)*元素下标index
- 09、对与指针p±n而言,实际上加减的值不是n,而是n * (sizeof (element))
- 10、数组名为常量指针不可对其进行赋值或修改,但可用于加减操作。如:
int a[10]={};//a为整型数组
int *p = a;
/*
则 *(a + n)、a[n]、*(p+n)、p[n] 完全相同
但
a++是错误的,因为a为常量指针
p++是正确的,因为p不是常量指针
*/
- 11、如果指针p指向数组a的第3个元素,则p[-1]的值为数组a的第2个元素的值,如:
#include <stdio.h>
int main() {
int a[5]={1,2,3,4,5};
int *p=&a[2];
printf("p[-1]: %d\n",p[-1]);
return 0;
}
- 12、二维数组中指针的应用
/*
table包含3个1维数组
table表示0号数组的地址
*(table+i)表示第i号数组
**(table+i)表示第i号数组的首个元素
*(*(table+i)+j)表示i号一维数组中下标为j的元素
*/
#include <stdio.h>
int main() {
int table[3][2]={{1,2},{3,4},{5,6}};
printf("%d\n",**(table+1));
printf("%d\n",*(*(table+1)+1));
return 0;
}
- 13、const在指针中的应用及含义
const限定符告诉编译器被限定的变量的值不可修改,
用于限定修改权限,常用于变量定义和形参定义
从右向左理解
1.const char *sPtr; 指针sPtr 指向字符常量
*sPtr='a';引起编译器报错,不允许sPtr对指向对象值的修改
2.int *const ptr=&x;ptr是常量指针,指向整型变量x
*ptr =7;正确
ptr=&y;错误,常量指针不能重新其指向其它对象
3.const int *const ptr=&x;兼具以上两点
*ptr =7;错误
ptr=&y;错误
- 14、指向指针的指针
// 代码举例:
#include <stdio.h>
int main() {
int a;
int *p;
int **q;
a=25;
p=&a;
q=&p;
printf("a=%d\n",a);
printf("*p=%d\n",*p);
printf("**q=%d\n",**q);
return 0;
}
- 15、C语言中指针做函数参数传递二维数组有两种基本方法:
1、传递"数组指针",代码举例:
#include<stdio.h>
void output(int(*pa)[3],int n);
int main() {
int a[2][3]= {
{1,2,3},
{4,5,6}
};
output(a,2);
return 0;
}
void output(int(*pa)[3],int n) { //这个函数只能输出n行3列的二维数组
int i,j;
for(i=0; i<n; i++) {
for(j=0; j<3; j++)
printf("%d ",pa[i][j]);
printf("\n");
}
}
2、传递"指针数组",即:先将数组的行指针存储到一个指针数组中,再将指针数组传递到子函数中去。代码举例:
#include<stdio.h>
void output(int *pa[],int row,int col);
int main() {
int a[2][3]= {
{1,2,3},
{4,5,6}
};
int i;
int *pa[2];
for(i=0; i<2; i++ )
pa[i]=a[i];
output(pa,2,3);
return 0;
}
void output(int *pa[],int row,int col) { //这个函数更通用,但调用前,要做好准备工作。
int i,j;
for(i=0; i<row; i++ ) {
for(j=0; j<col; j++ )
printf("%d ", pa[i][j] );
printf("\n");
}
}