指针
1.概念
用于保存内存地址的变量,称为指针变量,简称指针
2.指针变量的定义
语法格式:
指针指向的数据类型 * 指针名称;
例如:
int * p; //p是指向int数据的指针变量,p中只能保存int型数据的地址
//把一个数据的地址保存到指针中时,就说该指针指向这个数据
3.指针的用法
int i = 100;
int * p;
p = &i ; //i的地址保存到p中
//此时:对于p来说,有三个相关的表达式,如下;
*p ——— 指针指向的数据
p ——— 指针的空间
&p ——— 指针的空间地址
4.指针的运算
1)赋值运算:=
//注意:左值和右值类型必须保持一致
int *p ;
char c = 10 ;
float f = 3.4 ;
int i = 123 ;
p = &c ; //错误
p = &f ;// 错误
p = &i ;//正确
2)取地址运算:&
表示数据在内存空间中的地址,该地址对应的值为空间的第一个字节的地址
3)取值运算: *
当指针指向某个数据,可以通过取值运算来表示该数据
例如:
int i = 10 ;
int *p = &i ;
*p —— 表示i
4)加法运算:+
//指针只能加一个整数
//指针假一个整数n,表示该指针向高地址方向偏移n倍的指针指向的数据长度
例如:
int main(void)
{
int i = 10;
int *p;
p = &i;
printf("&i = %p\n",&i);
printf("p = %p\n",p);
printf("p+1 = %p\n",p+1);
printf("p+3 = %p\n",p+3);
return 0;
}
结果:
&i = 0xbfc51a88
p = 0xbfc51a88
p+1 = 0xbfc51a8c //加4个字节--1*sizeof(int) 或 1*sizeof(i) 或 1*sizeof(*p)
p+3 = 0xbfc51a94 //加12个字节 ---- 3 * sizeof(int) 或 3*sizeof(i) 或 3*sizeof(*p)
5)减法运算:-
//指针可以减去一个整数
//指针减一个整数,表示该指针向低地址方向偏移n倍的指针指向的数据长度
例子:
int main(void)
{
int i = 10;
int *p;
p = &i;
printf("&i = %p\n",&i);
printf("p = %p\n",p);
printf("p-1 = %p\n",p-1); //减4个字节--1*sizeof(int) 或 1*sizeof(i) 或 1*sizeof(*p)
printf("p-3 = %p\n",p-3); //减12个字节--3*sizeof(int) 或 3*sizeof(i) 或 3*sizeof(*p)
return 0;
}
结果:
&i = 0xbf8f11c8
p = 0xbf8f11c8
p-1 = 0xbf8f11c4 //减4个字节
p-3 = 0xbf8f11bc //减12个字节
//同类型指针可以相减,相减结果为整数
例如:
int main(void)
{
int a[10] = {1,2,3,4,5,6,7,8,9,10};
int *p1,*p2;
p1 = &a[9];
p2 = &a[4];
printf("p1 = %p\n",p1);
printf("p2 = %p\n",p2);
printf("p1 - p2 = %d\n",p1 - p2);
return 0;
}
结果:
p1 = 0xbffdc4e4
p2 = 0xbffdc4d0
p1 - p2 = 5 //表示两个指针变量中的地址之间有多少个指针指向的数据长度的空间
6)关系运算:> >= <= == !=
表示两个地址的高低比较
5.const关键字用啦定义指针
int a = 10 , b = 20 ;
//用法一
const int * p1 = &a; 或 int const * p1 = &a;
*p1 = 100; //错误,在定义指针时,加了const,所以*p1为只读不能赋值
a = 11; //正确,不影响a
//用法二
int * const p2 = &a;
*p2 = 100;
p2 = &b; //p不能赋值,因为在定义时加const,所以,p为只读
printf("a = %d\n",a);
printf("*p = %d\n",*p);
//用法三
在定义指针时,把第一种用法和第二种用法合起来,例如:
const int * const p = &a;
//这时, * p和p都不能赋值
6.数组和指针的关系
//数组名称多重含义
int a[5] ;
//数组名a——表示数组在内存空间的名称,sizeof(a)
//数组名a——表示数组的第一个元素地址,而且时地址常量,a等价于 &a[0]
例如:
int main(void)
{
/*
int a[5] = {1,2,3,4,5};
int i;
printf("sizeof(a) = %d\n",sizeof(a));
printf("&a[0] = %p\n",&a[0]);
printf("a = %p\n",a);
for(i = 0; i < 5; i++)
printf("%d,%d\n",a[i],*(a+i)); //公式: a[i] 等价于 *(a+i)
*/
int b[2][3] = {{1,2,3},{4,5,6}};
int i,j;
for(i = 0; i < 2; i++)
for(j = 0; j < 3; j++)
printf("%d\t%d\t%d\n",b[i][j],*(b[i]+j),*(*(b+i)+j));
return 0;
}