当前位置:网站首页>C语言回顾(指针篇)
C语言回顾(指针篇)
2022-07-28 05:18:00 【最美的愿望一定最疯狂】
指针
指针就是一个地址。它指向(代表)了内存中的一块空间
指针的类型
1、指针的类型
把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型
2、指针所指向的类型
把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。
(1)int*ptr; //指针类型是int* 指针所指向的类型是 int
(2)int**ptr; //指针类型是int** 指针所指向的的类型是 int* 指向的内容也是一个指针a,这个指针a的类型是int* 指向的内容是int(这里的a是随便起的一个名字,方便描述)
(3)int(*ptr)[3]; //指针所指向的的类型是 int()[3]
(4)int*(*ptr)[4]; //指针所指向的的类型是 int*()[4] 指向的内容也是一个指针a,这个指针a的类型是int*()[4],a指向的类型int()[4],是有4个元素的数组,数组内容是int型(这里的a是随便起的一个名字,方便描述)
指针的运算
指针的自增自减运算的意义与通常的数值加减运算的意义不一样,其结果和指针指向的类型有关。
char a[20];
int *ptr=(int *)a; //强制类型转换并不会改变 a 的类型
ptr++;
指针所指向的类型是int,int的长度为4。ptr++,编译器对其增加了sizeof(int),所以ptr此时的值加了4,因为数组a是char类型,每个元素所占的长度为1,且地址连续,所以ptr此时所指的内容就是a[4]
struct Test
{
int Num;
char *pcName;
short sDate;
char cha[2];
short sBa[4];
}*p;
假设p 的值为0x100000。如下表表达式的值分别为多少?
p + 0x1 = 0x___ ?
(int)p + 0x1 = 0x___?
(int*)p + 0x1 = 0x___?
指针变量与一个整数相加减并不是用指针变量里的地址直接加减这个整数。这个整数的单位不是byte 而是元素的个数。所以:p + 0x1 的值为0x100000+sizof(Test)*0x1。至于此结构体的大小为20byte。所以p +0x1 的值为:0x100014。
(int)p + 0x1 的值呢?这里涉及到强制转换,将指针变量p 保存的值强制转换成型数。任何数值一旦被强制转换,其类型就改变了。所以这个表达式其实就是一个整型数加上另一个整数。所以其值为:0x100001。
( int*)p + 0x1 的值呢?这里的p 被强制转换成一个指向整型的指针。所以其值为:0x100000+sizof(int)*0x1,等于0x100004。
数组与指针
1、数组名
数组名相当于指针,指向数组的首地址
2、指针数组与数组指针
指针数组,数组中存储的内容是指针。数组指针,就是指向数组的指针。
int *p1[3]; // 指针数组 中括号[]的优先级高,因此与p1先结合,表示一个数组,这个数组中有3个元素,这3个元素都是指针,它们指向的是int型数据。可以这样来理解:如果有这个定义int p[3],很容易理解这是一个有3个int型元素的数组,那么把int换成int*,意味着数组里的元素类型是int*型(指向int型数据的指针)。
int (*p2)[3]; // 数组指针 小括号让p2与*结合,表示p2是一个指针,这个指针指向了一个数组,数组中有3个元素,每一个元素的类型是int型。可以这样来理解:如果有这个定义int p[3],很容易理解这是一个有3个int型元素的数组,那么把数组名p换成是*p2,也就是p2是一个指针,指向了这个数组。
int a = 1, b = 2, c = 3;
int *p1[3];
p1[0] = &a;
p1[1] = &b;
p1[2] = &c;
//如果p1++ ,则p1只是增加了sizeof(int),因为其指向的内容是int型。可以这样理解,中括号[]的优先级高,p1先与[]结合,再与*结合,p1与[3]结合后看做一个整体a 所以就变成了 int *a,所以指向的类型就是int
int a[3] = {1, 2, 3};
int (*p2)[3] = a;
printf("0x%x \n", p2++);
//如果p2++,则p2增加了12,因为其指向的类型是int ()[3],是一个包含三个元素的数组,其长度是12
a与&a
其实a和 &a结果都是数组的首地址,但他们的类型是不一样。a表示&a[0],也即对数组首元素取地址,a+1表示首地址+sizeof(元素类型)。&a虽然值为数组首元素地址,但类型为:类型 (*)[数组元素个数],所以&a+1大小为:首地址+sizeof(a)。
应该在了解数组名即是数组的首地址的同时,也要知道,数组名仅仅是“相当于”指针,而并非真的是指针,数组名是只是个常量(一个值为数组首元素地址的常量),所以不能进行++或者–运算。而常量更是无法取地址的,而之所以有&a,其实这里的a的意义早已经不是当初那个数组名了,它此时代表了整个数组。
结构体与指针
1、需要使用->箭头操作符来获取结构体中的成员变量
2、结构体名字不是地址,需要对其进行取址(&)操作。
函数与指针
函数指针,其本质是一个指针变量,该指针指向这个函数。总结来说,函数指针就是指向函数的指针。函数的名字就代表函数的地址。
/* 声明格式 类型说明符 (*函数名) (参数) */
int (*fun)(int x,int y);
/* 将一个函数的地址赋值给函数指针 下面两种方式都可以*/
fun = &Function;
fun = Function;
/* 函数指针的调用 下面两种都可以,建议第一种,清晰明确 */
x = (*fun)();
x = fun();
函数指针数组
int (*p[4])(int, int);//先分析中间部分,标识符p与中括号[]结合(优先级高),所以p是一个数组,数组中有4个元素;然后剩下的内容表示一个函数指针,那么就说明数组中的元素类型是函数指针,也就是其他函数的地址
/* 示例代码 */
int add(int a, int b) { return a + b; }
int sub(int a, int b) { return a - b; }
int mul(int a, int b) { return a * b; }
int divide(int a, int b) { return a / b; }
int main()
{
int a = 4, b = 2;
int (*p[4])(int, int);
p[0] = add;
p[1] = sub;
p[2] = mul;
p[3] = divide;
printf("%d + %d = %d \n", a, b, p[0](a, b));
printf("%d - %d = %d \n", a, b, p[1](a, b));
printf("%d * %d = %d \n", a, b, p[2](a, b));
printf("%d / %d = %d \n", a, b, p[3](a, b));
}
指针函数,简单的来说,就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。
/* 声明格式 类型标识符 *函数名(参数表)*/
int *fun(int x,int y);//返回值是一个地址
边栏推荐
- Simpledateformat thread unsafe and datetimeformatter thread safe
- 【单例模式】懒汉模式的线程安全问题
- VMware Workstation is incompatible with device/credential guard. Disable device/credential guard
- (dark horse) MySQL beginner advanced notes (blogger lazy dog)
- RESNET structure comparison
- openjudge:大小写字母互换
- 2021CSDN博客之星评选,互投
- JVM note 4: Memory Model
- repackag failed: Unable to find main class
- openjudge:找第一个只出现一次的字符
猜你喜欢

顺序表oj之删除特定的元素

Custom JSON return data

多模块打包:程序包:xxx不存在

Merge two ordered arrays of order table OJ

Digital twin solutions inject new momentum into the construction of chemical parks

蒙特卡罗方法求解圆周率π并用turtle画点,以及完成进度条问题

Thesis writing function words

How Visio accurately controls the size, position and angle of graphics

repackag failed: Unable to find main class

How to compare long and integer and why to report errors
随机推荐
Openjudge: find all substring positions
(dark horse) MySQL beginner advanced notes (blogger lazy dog)
MySQL adds sequence number to query results
[idea plug-in artifact] teaches you how to set all attributes in an entity class with one click of idea
排序之插入排序
How Visio accurately controls the size, position and angle of graphics
openjudge:判断字符串是否为回文
Feignclient calls the get method and reports an error resultvo{result= unknown exception. Exception details: request method 'post' not supported
About localdatetime in swagger
环形链表问题
openjudge:字符串最大跨距
Docker deploy mysql5.7.35
SSM project quick build project configuration file
Openjudge: stone scissors cloth
冶金物理化学复习 --- 冶金反应动力学基础与多相反应动力学特征
科研论文写作方法:在方法部分添加分析和讨论说明自己的贡献和不同
JVM篇 笔记4:内存模型
Openjudge: campus accommodation reservation system
低照度图像数据集
Pytorch uses maxpool to realize image expansion and corrosion