当前位置: 首页 > article >正文

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 为指向空类型的指针变量,不指向具体的对象

http://www.kler.cn/a/144435.html

相关文章:

  • C++类与对象(6)—初始化列表、explicit关键字、static成员
  • 日历视图,轻松解决时间管理难题丨三叠云
  • A. Weird Sum - 思维
  • 【AI认证笔记】NO.2人工智能的发展
  • 字符串函数
  • 绿色能源守护者:光伏运维无人机
  • C++初阶 | [六] 模板初阶
  • 02 _ 架构分层:我们为什么一定要这么做?
  • idea git将某个分支内的commit合并到其他分支
  • 汽车电子 -- 车载ADAS
  • macos安装小软件 cmake
  • 6 个有效且可用的顶级 Android 数据恢复工具
  • 【深度学习】P1 数据缺失值预处理
  • 【Linux】Linux权限管理
  • 最新AI创作系统ChatGPT系统运营源码,支持GPT-4图片对话能力,上传图片并识图理解对话,支持DALL-E3文生图
  • 深度学习+不良身体姿势检测+警报系统+代码+部署(姿态识别矫正系统)
  • 【分布式】分布式事务及其解决方案
  • JAVA 面向对象编程
  • Vue中项目进行文件压缩与解压缩 (接口返回文件的url压缩包前端解析并展示出来,保存的时候在压缩后放到接口入参进行保存)
  • C语言 移位操作符