C语言指针

指针

一个变量的地址称为该变量的指针。

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

指针变量的声明

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

c 复制代码
			类型名 * 指针变量名;

在变量名前面加*号表示该变量是指针变量。

指针变量的类型就是该指针变量指向的变量的类型。

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

在声明指针变量时应注意:

定义指针变量时必须指定数据类型。

C语言要求每个指针变量只能指向一种特定类型(引用类型)的对象。

初始化指针变量

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

先声明指针变量,再初始化指针变量。

c 复制代码
int a = 10;
int *p;  
p = &a;      //将a的地址赋给指针p

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

c 复制代码
int a = 10;     
int *p = &a; //将a的地址赋给指针p

说明:&a 为变量 a 的地址,p 为指针变量, *p 为 p 当前所指向的对象。

不能用一个整数给一个指针变量赋值。

间接寻址运算符

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

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

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

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

指针变量赋值

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

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

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

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

指针作函数参数

因为C语言用值进行参数传递,所以在函数调用中用作实际参数的变量无法改变。

变量的地址作为函数的参数,可以实现通过调用函数使变量的值发生变化,在主调函数使用这些改变了的值。

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 表明函数不会改变指针参数所指向的对象。

c 复制代码
void f(const int *p) {} //p是指向"常整数"的指针,不能试图改变*p

指针作为返回值

指针作为返回值的函数简称指针函数。

定义指针函数的一般形式:

C 复制代码
			类型名 * 函数名(参数列表);

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

c 复制代码
/*返回两个整数中较大的那个整数的地址*/
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语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*

例:

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;
}

指针数组

一个数组,若其元素均为指针类型数据,该数组称为指针数组。

定义一维指针数组的一般形式为:

c 复制代码
		类型名 * 数组名 [数组长度];

也就是说,指针数组中的每一个元素都存放一个地址,相当于一个指针变量。

声明一个数组,包含 4 个元素,每个元素的类型是 int 型指针:

c 复制代码
int* p[4]; //等价于 int* (p[4]) 

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

c 复制代码
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;
}

指向函数的指针

指向函数的指针简称函数指针。

一个函数在编译时被分配给一个起始地址(入口地址);每次调用函数时,都从该地址开始执行此段函数代码。

函数名就代表函数的起始地址。

定义指向函数的指针一般形式:

c 复制代码
		函数类型 (*变量名) (函数参数列表)

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

c 复制代码
int (*p)(int,int); //等价于int (*p)(int a,int b);      

括号不能省略,p 先与*结合,表示它是指针变量。

通过函数指针调用函数:

c 复制代码
/*取两个整数中大的那个*/
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* p int* 定义 p 为指向整型数据的指针变量
const int* p const int* p 是指向常量的指针变量,不能通过 p 改变其指向的对象的值
const int const *p const 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* *p int* * p 为指针变量,它指向一个指向整型数据的指针变量
void* p void* 定义 p 为指向空类型的指针变量,不指向具体的对象
相关推荐
Cao1234567893219 分钟前
扫雷-C语言版
c语言·开发语言
天堂的恶魔94620 分钟前
QT —— 信号和槽(槽函数)
开发语言·qt
水w26 分钟前
【Python爬虫】详细入门指南
开发语言·爬虫·python·scrapy·beautifulsoup
GZX墨痕1 小时前
从零学习直接插入排序
c语言·数据结构·排序算法
Susea&1 小时前
数据结构初阶:双向链表
c语言·开发语言·数据结构
Net_Walke1 小时前
【C数据结构】 TAILQ双向有尾链表的详解
c语言·数据结构·链表
pianmian12 小时前
arcgis几何与游标(1)
开发语言·python
-曾牛2 小时前
【LangChain4j快速入门】5分钟用Java玩转GPT-4o-mini,Spring Boot整合实战!| 附源码
java·开发语言·人工智能·spring boot·ai·chatgpt
TDengine (老段)2 小时前
TDengine 语言连接器(Node.js)
大数据·c语言·数据库·物联网·node.js·时序数据库·tdengine
nanzhuhe2 小时前
python中参数前**的含义
开发语言·python