指针部分较难的知识点

指针部分较难的知识点

1.通过指针引用多维数组(本文中仅说明二维数组)

以int a[3][4]为例:
(1)a[0],a[1],a[2]均为一维数组名,则a[0]=&a[0][0] (C语言规定一维数组名代表数组首元素地址)
(2)a+1=(a+1)的值相同,(a+1)=a[1]. a+1虽然等于a[1],但是二者含义不同,a+1表示第1行的首址,而a[1]=a[1]+0表示a[1][0]的地址,因此对a+1与a[1]分别加1会得到不同的值
事实上,a[1]的类型为int* 型,而a+1为 int(*)[4]型
 (3)int ( * a ) [4]与 int * a[4]的区别,很难理解

int a[3][4];
int (* p)[4]; (*和p先结合,表示*p(即p所指的)是一个维度为4的int型数组
p=a;

int * a[4]很好理解,a先与[4]结合表示一个4维数组,int *为数组类型,即一个4维指针数组。
 (4)一维数组与二维数组在使用指向一维数组的指针进行遍历时,对初始化时的区别,很难理解

int a[3][4];
int (*p)[4];
p=a;
int a[4];
int (*p)[4];
p=&a;

对一维数组,虽然&a=a,但是,&a表示取整个数组第0行的地址,与a含义不同,可编程检验&a+1和a+1的值分别为多少

2.指向指针数据的指针。

例如: char * p; p之前有两个号,由于*运算符的结合性是从右往左的,所以 char * *p = char * (*p)。等式右边可以这样理解,*p表示p是一个指针 char *表示这个指针的数据类型是 char *型的,即指针p指向的数据是一个char型的指针
上代码😝:

 #include <stdio.h>
 int  k=7;
 void f(int  **s)
 {  int  *t=&k;
    *s=t;
    printf("%d,%d,%d,", k, *t, **s); 
 }
 main()
 {  int  i=3,*p=&i, **r = &p;
    f(r);     printf("%d,%d,%d\n", i, *p, **r); 
 }

运行结果:

[Running] cd "e:\C-programming-review\" && gcc project1.c -o project1 && "e:\C-programming-review\"project1
7,7,7,3,7,7
[Done] exited with code=6 in 0.524 seconds

分析:指针的指针。
本题各个变量的数据类型分别为:
i,k为整型变量,
p,t为整型指针,
r,s为指针,不过它们所指向的内容还是指针。

难理解:main函数中先让p指向i,即*p=i,再让r指向p,即 *r=p,**r= *p=i;再执行f(r),将r作为实参传给s,则 s=r, *s= *r=p,再让t指向k,即 *t=k,故此时 *s= *r=p=t,指针s所指向存储区域的内容变为t,又因为指针s和指针r指向同一片区域,故导致指针r所指向存储区域的内容变为t,又因为指针r所指向的区域为指针变量p的内容,故指针变量p的内容变为t,故在f函数调用结束后, **r= *p= *t=k=7.
本题可与上面的第3题对照着理解
在下面的代码段2中,函数的参数是指针变量,而本题函数的参数是指针的指针,
并且,在代码段2中,并没有改变指针所指向的变量的值,改变的只是指针的值,故在函数调用完以后,函数外部作为实参的那个指针没有发生任何变化;而本题在所调用的函数中改变了指针所指向的变量的值,所以函数外部作为实参的指针和它所指向的变量的值都发生了变化。

作为对比,代码段2😝:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct stu {  
    char  *name, gender;
    int  score; 
} STU;
void f(char  *p)
{  
    p=(char *)malloc(10);   
    strcpy(p, "Qian");  
}
main()
{  
    STU  a={NULL, 'm', 290}, b;
    a.name=(char *)malloc(10);
    strcpy( a.name, "Zhao" );
    b = a;
    f(b.name);
    b.gender = 'f';   b.score = 350; 
    printf("%s,%c,%d,", a.name, a.gender, a.score);
    printf("%s,%c,%d\n", b.name, b.gender, b.score);
}

本题考查指针作为函数的形参,在调用f函数时,b.name作为f函数的实参传递给形参p,但进入f函数的函数体之后,只是对指针p进行操作,并且f函数调用结束后,形参p指针的值不会回传给实参b. name。故b.name与a.name所指向区域的内容未发生变化

3.函数指针与指针函数:

函数指针的意思是某个指针所指向的内容是一个函数,而指针函数的意思是某个函数的返回值是一个指针。
例如:

int *f(int a, int b)

这是定义了一个指针函数,()运算符的优先级高于*运算符,故f会先于()结合,表示f是一个函数,int *表示这个函数的返回值是一个整型指针。故

 int *f(int a, int b)= (int *) f(int a, int b)
 int (*f)(int a, int b)

从左往右看,*f表示f是一个指针,它所指向的是一个函数😀

参考文献

《C程序设计》第四版 by 谭浩强

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

科研程序开发

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

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

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

打赏作者

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

抵扣说明:

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

余额充值