指针_C语言快速入门与计算机二级备考
指针概念
-
指针就是保存地址的变量
-
int *p = &i;
* 表示这是一个指针,p指向i,p这个变量保存了i这个变量的地址注意:
int* p,q
p是指针,q只是普通变量;想让两者都是指针:int *p,*q
-
普通变量的值是实际值,指针变量的值是具有实际值的变量的地址
使用一个指针变量,必须在指向另一个变量之后 再使用指针
指针运算
地址与变量
- &与*这两个运算符相互起反作用
& 取地址符
-
它的作用是获得变量的地址,操作数必须是变量
无法对没有地址的变量取地址,必须是一个明确的变量
-
在输出时 %p的占位符表示地址 输出的数带有0x前缀
-
地址的大小是否与int相同取决于编译器,所以输出地址时不能直接用整数形式
-
对于一个数组:&a=a=a[0],三者地址相同
相邻单元的地址间的差距是4个字
* 访问指针所表示地址的变量
-
*是一个单目运算符(区别于乘的运算符),用以访问指针所表示地址上的变量
得到的变量可作左值也可作右值(左值并非变量,而是可以接收值的值,是运算的结果)
-
例如:
int k = *p
指针与整数运算
对指针加减的含义
-
指针+1运算,在其地址上+数据类型的一个sizeof( )
实际上使得指针指向了下一个单元
减即为指向上一个单元
-
指向同一批连续分配的空间时,指针运算才有意义
-
当
char ac[]={……}
char *p=ac
时,*(p+n) = ac[n]
-
需要注意指针本身是分频的内存地址值,不能用整数赋值指针变量作为地址值
-
指针相减
两个指针相减,结果是 两个指针指向的地址的差/sizeof(当前的数据类型)
这样的运算告诉你这两个地址之间有几个这样类型的单元
-
指针递增
*p++
取出p所指的数据,并且把p移到下一位++的优先级比*更高
指针比较
- 指针也可使用关系运算符 <,<=,==,>=,>,!= 比较它们在内存中的地址
- 数组中的单元的地址肯定是线性递增的
指针的类型
-
无论指向什么类型,指针本身的大小是一样的(都是地址)
-
指向不同类型的指针是不能直接互相赋值的
-
特殊的指针
特殊的:void* 表示不知道指向什么的指针 计算时同char*(但不相通)
指针可以指向函数入口:有函数
int fun(参数表);
可用函数指针int(*f)(参数表)
调用函数赋值为NULL的指针称空指针,其作用为操作系统保留,不能用于访问数据
-
指针类型转换
int *p =&i;
void *q = (void*)p
这不会改变p所指的变量类型,而是在之后用q的不同的眼光通过p看它所指的变量
指针应用
作为参数使用
-
向函数传入较大的数据时,用指针作参数,例如传入数组,同时在传入后通过指针对数组作操作
-
例如:
void f(int *p);
在被调用时得到了某个变量的地址:
int i=0; f(&i);
-
在函数里可以通过这个指针访问外面的变量
在不同的函数中,原本只能传递值给函数,借由指针我们能够获得外面变量的地址,从而获得访问外部函数的能力
但是指针变量本身作为函数参数,也要遵守形参实参数据单向传递的规则,调用函数不能改变实际参数指针变量的值,通过函数不能改变指针所指
-
例如在函数本地变量章节的无法使用的swap函数可通过指针实现:
void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int main() { int a = 10; int b = 2; swap(&a, &b);//交上a与b的地址 printf("a=%d,b=%d", a, b); return 0; }
-
函数要返回多个值,某些值只能通过指针返回
传入的参数实际上是需要保存带回的结果的变量
返回结果
-
返回不止一个结果,或是需要用函数来修改不止一个变量,也会用到指针
-
例如:
函数自身的返回值用于返回运算的状态,运算结果用指针返回
运算可能出错,需要另一种途径表达错误,一般让函数返回一个特殊的,不属于有效范围内的值表示出错,比如-1或0
数组与指针
数组和指针的关系
-
函数参数表中的数组实际上是一个指针
-
数组作函数参数
这两种函数原型的参数等价
int sum(int
*ar
,int n)
=int sum(int
ar[]
,int n)
告知了传入的是数组,并用另一个参数n传入数组下标
-
数组变量实际上是特殊的指针
例如:
int a[10]; int*p=a;
因为数组变量本身就表达地址,所以无需再用&取地址a
的地址是数组的首个单元,不能用指针指向整个数组而
a==&a[0];
数组的单元表达的是变量,需要用&取地址例如:
scanf("%d",&a[2]);
输入一个数赋给数组a的第三个单元的地址
两者的运算
-
数组的[ ]运算符也可用于指针,将指针所指的部分当作只有一个元素的数组来处理
例如:指针p指向一个值为2的变量的地址,
p[0]
相当于*p
=2 -
指针的*运算符也可用于数组
例如:数组a包括100,2,4三个数,这时
*a
相当于a[0]
=100 -
数组变量是一个const的指针,所以不能被赋值改变
例如:
int *b
相当于int *const b
指针数组
-
int *ptr[10]
表示一个指针数组,其有10个元素,每个元素都是指向int的指针,p[0]
表示某一个地址,*p[0]
表示这个地址存放的数 -
而
int(*ptr)[10]
则是一个指向一个含10个int元素的一维数组的指针,(*ptr)[0]
将会得到这个数组的第一个元素对于二维数组,可以使用这种指针对每一行进行操作,例如:
int arr[3][4] = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}}; int (*p)[4] = arr; // p 现在指向 arr 的第一行 printf("%d\n", (*p)[0]); // 输出 1 printf("%d\n", p[1][2]); // 输出 7,因为 p[1] 是指向 arr[1] 的指针
指针与const
-
通过const在*的前后判断const的是所指还是指针
*前const后:指针是const,
int *const p=&i
const前*后:所指是const,
const int* p=&i
与int const* p=&i
意义一致 -
指针是const
-
如果一个指针是const,那么它一旦得到了某个变量的地址,就不能再指向其它变量
-
但是,想更改q的所指,比如
q++
这样的操作是不行的 -
例如:
int* const q =&i;
这之后*q=24
是可以的,因为q所指向的i并不是const但是,不能更改q的所指,比如
q++
这样的操作是不行的
-
-
所指是const
-
表示不能通过这个指针去修改所指的变量(但那个变量并不会成为const)
-
例如:
const int *p =&i;
这之后可以让i=26
,也可以改变p的所指,让*p=&j
,但是不可以让
*p=24
,即不能通过p来改变它所指的i
-
本文来自博客园,作者:无术师,转载请注明原文链接:https://www.cnblogs.com/untit1ed/p/18547827
本文使用知识共享4.0协议许可 CC BY-NC-SA 4.0
请注意: 特别说明版权归属的文章以及不归属于本人的转载内容(如引用的文章与图片)除外
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了