C语言指针

指针

一个变量的地址称为该变量的指针。
使用一个变量来存放另外一个变量的地址,这样的变量被称为指针变量。

指针变量的声明

声明指针变量的一般形式:

			类型名 * 指针变量名;

在变量名前面加*号表示该变量是指针变量。
指针变量的类型就是该指针变量指向的变量的类型。

int *p1, *p2;  //指向int类型对象的指针变量
char *r;
double *d; 

在声明指针变量时应注意:
定义指针变量时必须指定数据类型。
C语言要求每个指针变量只能指向一种特定类型(引用类型)的对象。

初始化指针变量

初始化指针变量的方法是:使用取地址运算符(&)把某个变量的地址赋给它。
先声明指针变量,再初始化指针变量。

int a = 10;
int *p;  
p = &a;      //将a的地址赋给指针p

声明指针变量的同时初始化。

int a = 10;     
int *p = &a; //将a的地址赋给指针p

说明:&a 为变量 a 的地址,p 为指针变量, *p 为 p 当前所指向的对象。
不能用一个整数给一个指针变量赋值。

间接寻址运算符

一旦指针变量指向了对象,就可以使用间接寻址运算符(*)访问存储在对象中的内容。

int a = 10;
int * p = &a;   //p指向了变量a
*p = 1;         //将1赋给p指向的变量,即a = 1,*p = 1

不要把间接寻址运算符用于未初始化的指针变量。

int *p; //错误,*p、p 的值未定义
*p = 1; //错误,可能会修改存储在未知地址的数据。

指针变量赋值

C语言允许使用赋值运算符进行指针的复制,前提是两个指针具有相同的类型。

int a = 10;
int *p1, *p2; //定义了指向int类型的指针变量
p1 = &a;      //p1指向了a
p2 = p1;      //把a的地址复制给了p2,p2同样也指向了a
*p1 = 0;      //a等于0
*p2 = 5;      //a等于5

任意数量的指针变量都可以指向同一个对象。

int i = 1, j = 2;
int *p = &i; //p指向了i
int *q = &j; //q指向了j
*p = *q;     //将 j(*q)的值赋值给 i(*p)

指针作函数参数

因为C语言用值进行参数传递,所以在函数调用中用作实际参数的变量无法改变。
变量的地址作为函数的参数,可以实现通过调用函数使变量的值发生变化,在主调函数使用这些改变了的值。

void swap(int* p1, int* p2) {
    int temp = *p1;
    *p1 = *p2;
    *p2 = temp;
}
int main()
{
    int a = 10,b = 20;
    swap(&a,&b); // a = 20,b = 10
}

用const保护参数

可以使用 const 表明函数不会改变指针参数所指向的对象。

void f(const int *p) {} //p是指向“常整数”的指针,不能试图改变*p

指针作为返回值

指针作为返回值的函数简称指针函数。
定义指针函数的一般形式:

			类型名 * 函数名(参数列表);

函数调用()的优先级高于*,因此函数名先和括号相结合。

/*返回两个整数中较大的那个整数的地址*/
int* max(int *a,int *b)
{
	if(*a > *b)
		return a; //返回指针 a
	else
		return b; //返回指针 b
}
main()
{
	int i = 10;
	int j = 5;
	int *p = max(&i,&j); //*a 是 i 的别名,*b 是 j 的别名
}

函数也可以返回指向外部变量或指向声明为 static 的局部变量的指针。
永远不能返回指向自动局部变量的指针。

指向指针的指针

如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。
指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。
C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*
例:

int main()
{
    int i = 10;
    int* p1 = &i;   //p1 是一级指针,指向普通类型的数据
    int** p2 = &p1; //p2 是二级指针,指向一级指针
    printf("%d,%d\n",*p1);
    printf("%d,%d\n",**p2);
	return 0;
}

指针数组

一个数组,若其元素均为指针类型数据,该数组称为指针数组。
定义一维指针数组的一般形式为:

		类型名 * 数组名 [数组长度];

也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。
声明一个数组,包含 4 个元素,每个元素的类型是 int 型指针:

int* p[4]; //等价于 int* (p[4]) 

由于[]*优先级高,因此 P 先与[]结合,形成数组形式,然后再与*结合。

int main()
{
    int i = 10;
    int j = 12;
    int k = 15;
    int* arr[3] = {&i,&j,&k}; //arr 是指针数组
    int** p = arr;  //p 是二级指针,指向 int* 
    printf( "%d\n", **(p + 1) ); //指针访问数组元素 j
    printf( "%d\n", *p[1] );     //下标访问数据元素 j
	return 0;
}

指向函数的指针

指向函数的指针简称函数指针。
一个函数在编译时被分配给一个起始地址(入口地址);每次调用函数时,都从该地址开始执行此段函数代码。
函数名就代表函数的起始地址。
定义指向函数的指针一般形式:

		函数类型 (*变量名) (函数参数列表)

声明 p 是一个指向函数的指针,它可以指向函数类型为整型且有两个整型参数的函数:

int (*p)(int,int); //等价于int (*p)(int a,int b);      

括号不能省略,p 先与*结合,表示它是指针变量。
通过函数指针调用函数:

/*取两个整数中大的那个*/
int max(int a, int b)
{
    return a > b ? a : b;
}
int main()
{
    int (*p) (int, int);
    p = max; //函数指针变量赋值
	printf( "%d\n", p(7, 6) );//调用 max 函数
	return 0;
} 

说明:

  • 指向函数的指针,只能指向在定义时指定的类型的函数(函数类型和形参列表匹配)。
  • 在给函数指针赋值时,只须给出函数名而不必给出参数。
  • 用函数指针调用函数时,须用指针变量名代替函数名。
  • 对指向函数的指针不能进行算术运算。

指针的数据类型小结

变量定义类型表示含义
int* pint*定义 p 为指向整型数据的指针变量
const int* pconst int*p 是指向常量的指针变量,不能通过 p 改变其指向的对象的值
const int const *pconst int const *p 是指向常量的常指针,其指向不能改变,且不能通过 p 改变其指向的对象的值
int* p()int* ()p 为返回一个指针的函数,该指针指向整型数据
int (*p) ()int (*) ()p 为指向函数的指针,该函数返回一个整型数据
int* p[4]int* [4]定义 p 为指针数组,它由4个指向整型数据的指针元素组成
int (*p) [4]int (*) [4]p 为指向包含4个元素的一维数组的指针变量
int* *pint* *p 为指针变量,它指向一个指向整型数据的指针变量
void* pvoid*定义 p 为指向空类型的指针变量,不指向具体的对象
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往昔的恒纳兰那

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值