AutoLeaders控制组——c语言指针笔记

c语言指针笔记

声明:该笔记主要来源于翁恺c语言和网页知识的总结。

1.运算符&

1.1 &与scanf:

1.1.1 在计算机中每个编码的变量都有它对应的地址,相当于它的位置,在编程时,变量的值可以改变,但是地址不会变,输出地址时的值默认都是十六进制的。
1.1.2在scanf中出现的&符号scanf("%d",&i); 实际上是函数scanf读取了i的地址,再用printf输出才能输出i的值。

1.2 &与数组:

1.2.1 在printf地址的值时需要用%p,如printf("%p",&i);&可以取变量的地址,也可以取数组的地址。
1.2.2 在取数组的地址时,实际上是取到的是数组的第一位元素的地址。如定义数组int a[3]={1,2,3,};,在用&取地址时,取到的是a[0]的值。

2.指针:保存地址的变量

2.1 理解指针:

2.1.1 *是一个单目运算符,我们用*来声明指针,如int *p;就是一个int类型的指针,因此p在这里就是保存地址的变量。而对于int *p=&i;我们称:指针p指向了i;又等同于此时p的值就是i的地址。
2.1.2 对于int *p,q;表示p是一个int类型的指针,q是一个int变量,要同时定义q和q为指针需写成int *p,*q;,int*并不是一个数据类型,普通变量表示的是实际值,而指针变量表示的是实际值的地址。
2.1.3 指针取值
用函数:如定义函数void f(int *p),在先行定义了int i;之后我们调用函数可以用f(&i)来取i的地址,并可以在函数f内通过地址访问i。如图所示,i的地址的值在函数内外都是一致的
如图,i的地址在函数内外都是一致的。
当数用:在函数中使用指针,如下图所示
在这里插入图片描述
在函数f中,我们用*p来表示整体,表示一个int类型的整数,其值就是i,因为我们之前取了i的地址,此时*p的值就是i。
注意:在调用函数时()内是&加变量,表示读取地址。而定义时用的是*加变量。可参考上图中指针p和i。

2.2 应用指针:

2.2.1 交换变量的值
我们可以在不直接改变参数值的情况下,进行变量交换并输出,如下所示
`#include <stdio.h>

void swap(int*pa,int pb);
int main(){
int a=1;
int b=2;
swap(&a,&b);
}
void swap(int
pa,int *pb){
int t=*pa;
*pa=*pb;
*pb=t;
printf(“a=%d\n”,*pa);
printf(“b=%d”,*pb);
}`
同时如果我们对函数内的 *pa或者 *pb进行修改,函数外对应的a或者b的值也会改变,但是不变的是地址。
2.2.2 函数传回多个值
下面我们通过一个找数组最大最小值的函数来进行说明
在这里插入图片描述
在上述图片中,我们在函数外定义了max和min两个变量,并读入了它们的地址,在函数中进行修改,最终带回了max和min两个结果。
2.2.3 在无法通过简单比较得出结论的判断语句中,我们用函数带回的值进行是否的判断。如下图所示。
在这里插入图片描述
我们在上述if语句中,通过函数带回的值是否等于0来决定语句的执行情况。
注意:在定义指针时,应决定好其指定的方向。

2.3 指针与数组:

2.3.1 数组变量是特殊的指针:
在取数组地址时,我们可以不加&符号int *p=a; a为一个数组。
但是对数组元素取地址时,需要加&;int *p=&a[0];
在定义好数组a[]后,*a表示的值就是a的第一位元素。
但是数组变量不能被赋值,但是其单位可以,因为数组变量实际是const类型的指针。即int *p=a[];可以成立,但是int b[]=*a;不能成立。
2.3.2 在我们定义函数的参数表中,数组可以写成指针的形式,如下函数其实是等价的。
在这里插入图片描述
2.3.3 在指针p已经指向一个数组的情况下,p++指的就是数组的下一位。

2.4 二级指针:

2.4.1 指针可以指向一份普通类型的数据,例如 int、double、char 等,也可以指向一份指针类型的数据,例如 int *、double *、char * 等。

2.4.2 如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。

2.4.3 假设有一个 int 类型的变量 a,p1是指向 a 的指针变量,p2 又是指向 p1 的指针变量,即(指向指针的指针),将这种关系转换为C语言代码:

int a =100;
int *p1 = &a;
int **p2 = &p1;

2.4.4 指针变量也是一种变量,也会占用存储空间,也可以使用&获取它的地址。C语言不限制指针的级数,每增加一级指针,在定义指针变量时就得增加一个星号*。p1 是一级指针,指向普通类型的数据,定义时有一个*;p2 是二级指针,指向一级指针 p1,定义时有两个*。

2.4.5 如果我们希望再定义一个三级指针 p3,让它指向 p2,那么可以这样写:

int ***p3 = &p2;

四级指针也是类似的道理:

int ****p4 = &p3;

实际开发中会经常使用一级指针和二级指针,几乎用不到高级指针。

2.4.6 补充指针数组

如果一个数组中的所有元素保存的都是指针,那么我们就称它为指针数组。指针数组的定义形式一般为:
dataType arrayName[length];
[ ]的优先级高于
,该定义形式应该理解为:
dataType *(arrayName[length]);

括号里面说明arrayName是一个数组,包含了length个元素,括号外面说明每个元素的类型为dataType *。

除了每个元素的数据类型不同,指针数组和普通数组在其他方面都是一样的,下面是一个简单的例子:

#include <stdio.h>
int main(){
int a = 16, b = 932, c = 100;
//定义一个指针数组
int *arr[3] = {&a, &b, &c};//也可以不指定长度,直接写作 int *arr[]
//定义一个指向指针数组的指针,两个 *号具有抵消的作用。
int **parr = arr;
printf(“%d, %d, %d\n”, *arr[0], *arr[1], *arr[2]);
printf(“%d, %d, %d\n”, **(parr+0), **(parr+1), **(parr+2));

return 0;
}
运行结果:
16, 932, 100
16, 932, 100

arr 是一个指针数组,它包含了 3 个元素,每个元素都是一个指针,在定义 arr 的同时,我们使用变量 a、b、c 的地址对它进行了初始化。

parr 是指向数组 arr 的指针,确切地说是指向 arr 第 0 个元素的指针,它的定义形式应该理解为int *(parr),括号中的表示 parr 是一个指针,括号外面的int *表示 parr 指向的数据的类型。arr 第 0 个元素的类型为 int *,所以在定义 parr 时要加两个 *。

第一个 printf() 语句中,arr[i] 表示获取第 i 个元素的值,该元素是一个指针,还需要在前面增加一个 * 才能取得它指向的数据,也即 *arr[i] 的形式。

第二个 printf() 语句中,parr+i 表示第 i 个元素的地址,*(parr+i) 表示获取第 i 个元素的值(该元素是一个指针),**(parr+i) 表示获取第 i 个元素指向的数据。

指针数组还可以和字符串数组结合使用,请看下面的例子:

#include <stdio.h>
int main(){
char *str[3] = {
“c.biancheng”,
“C语言指针笔记”,
“C Language”
};
printf(“%s\n%s\n%s\n”, str[0], str[1], str[2]);
return 0;
}

运行结果:
c.biancheng
C语言指针笔记
C Language

注意:字符数组 str 中存放的是字符串的首地址,不是字符串本身,字符串本身位于其他的内存区域,和字符数组是分开的。也只有当指针数组中每个元素的类型都是char *时,才能像上面那样给指针数组赋值,其他类型不行。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值