C语言指针知识体系搭建

指针知识体系搭建前言先从整体上把握指针的知识体系。然后突破一级指针、二级指针、多级指针。指针强化铁律1:指针是一种数据类型既然指针是一种数据类型,那么指针也是一种变量,占有一定的内存空间,存储一定的值。问题:那么指针的内存大小是多少了?//测试指针的内存大小#include "stdlib.h"#include "stdio.h"int main() { char*...
摘要由CSDN通过智能技术生成

指针知识体系搭建

前言

先从整体上把握指针的知识体系。然后突破一级指针、二级指针、多级指针。

指针强化

铁律1:指针是一种数据类型

  1. 既然指针是一种数据类型,那么指针也是一种变量,占有一定的内存空间,存储一定的值。问题:那么指针的内存大小是多少了?
//测试指针的内存大小
#include "stdlib.h"
#include "stdio.h"
int main() 
{   
	char* p1 = NULL;
	int* p2 = NULL;
	printf_s("sizeof(p1) = %d\n", sizeof(p1));
	printf_s("sizeof(p2) = %d\n", sizeof(p2));
	return 0;
}

在Debug模式是X86的环境下测试结果:
在这里插入图片描述
在Debug模式是X64的环境下测试结果:
X64下指针的内存大小
这个测试结果说明在不同的环境下,指针的内存大小也不同,在32位的编译环境下,指针的内存一般是4个字节,在64位的编译环境下。指针的内存一般是8个字节。

  1. *p操作内存
    在指针声明时,*号表示所声明的变量为指针
    在指针使用时,*号表示 操作 指针所指向的内存空间中的值
    *p相当于通过地址(p变量的值)找到一块内存;然后操作内存
    *p放在等号的左边赋值(给内存赋值)
    *p放在等号的右边取值(从内存获取值)
#include "stdlib.h"
#include "stdio.h"


int main() 
{   
	char* p1 = NULL;
	int a = 100; //定义一个变量
	p1 = &a;     //p1存储了是a的地址,相当于指针间接的取了变量的地址
	printf_s("*p = %d\n", *p1); //通过*p1间接的访问p1存储地址内部的值也就是a = 100
	*p1 = 200;                //间接的修改的a的值
	printf_s("a = %d", a);
}

测试结果
在这里插入图片描述

  1. 指针变量和它指向的内存块是两个不同的概念
    含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
    含义2 给p赋值p=‘a’; 不会改变指针变量的值,只会改变所指的内存块的值
    含义3 =左边p 表示 给内存赋值, =右边p 表示取值 含义不同切结!
    含义4 =左边char *p
    含义5 保证所指的内存块能修改

  2. 指针是一种数据类型,是指它指向的内存空间的数据类型
    含义1:指针步长(p++),根据所致内存空间的数据类型来确定
    p++=(unsigned char )p+sizeof(a);
    结论:指针的步长,根据所指内存空间类型来定。

#include "stdlib.h"
#include "stdio.h"


int main() 
{   
	char* p1 = NULL;
	int* p2 = NULL;
	printf_s("p1 = %d\n", p1);
	printf_s("p2 = %d\n", p2);
	p1++;
	p2++;
	printf_s("p1++ = %d\n", p1);
	printf_s("p2++ = %d\n", p2);
	return 0;
}

测试结果:
p++的步长
这个测试说明一个点就是尽管对于32位系统的指针都是char和int都是四个字节内存大小,但是指针的步进不同,对于char的由于他指向的内存是char型所以指针的步进是1,对于int由于指向的数据类型是int型所以其步进是4个字节,对于不同同类型的指针其内存对于32位系统都是占4个字节,但是步进是+sizeof(指向类型)。对于复杂的类型也是如此,比如结构体之类的。

注意: 建立指针指向谁,就把把谁的地址赋值给指针。图和代码和二为一。不断的给指针变量赋值,就是不断的改变指针变量(和所指向内存空间没有任何关.

铁律2:间接赋值(*p)是指针存在的最大意义

1)两码事:指针变量和它指向的内存块变量 ,换句话说指针变量是指向变量的地址,并不等于指向的内存变量本身。
2)条件反射:指针指向某个变量,就是把某个变量地址否给指针
3)*p间接赋值成立条件:3个条件
a)2个变量(通常一个实参,一个形参)
b) 建立关系,实参取地址赋给形参指针
c) *p形参去间接修改实参的值

Int iNum = 0; //实参
int *p = NULL;
p = &iNum;
iNum = 1;
*p =2 ; //通过*形参 == 间接地改变实参的值
*p成立的三个条件:

4)引申: 函数调用时,用n级指针(形参)改变n-1级指针(实参)的值。

//改变0级指针(int iNum = 1)的值有2种方式
//改变1级指针(eg char *p = 0x1111 )的值,有2种方式
//改变2级指针的(eg char **pp1 = 0x1111 )的值,有2种方式

//函数调用时,形参传给实参,用实参取地址,传给形参,在被调用函数里面用*p,来改变实参,把运算结果传出来。
//指针作为函数参数的精髓。

铁律3:理解指针必须和内存四区概念相结合

1)主调函数 被调函数
a)主调函数可把堆区、栈区、全局数据内存地址传给被调用函数
b)被调用函数只能返回堆区、全局数据
2)内存分配方式
a)指针做函数参数,是有输入和输出特性的。

铁律4:应用指针必须和函数调用相结合(指针做函数参数)

在这里插入图片描述
指针做函数参数,问题的实质不是指针,而是看内存块,内存块是1维、2维。
1)如果基础类int变量,不需要用指针;
2)若内存块是1维、2维。

铁律5:一级指针典型用法(指针做函数参数)

一级指针做输入
int showbuf(char *p)
int showArray(int *array, int iNum)
一级指针做输出
int geLen(char *pFileName, int *pfileLen);
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存

铁律6:二级指针典型用法(指针做函数参数)

二级指针做输入
int main(int arc ,char *arg[]); 字符串数组
int shouMatrix(int [3][4], int iLine);
二级指针做输出
int Demo64_GetTeacher(Teacher **ppTeacher);
int Demo65_GetTeacher_Free(Teacher **ppTeacher);
int getData(char **data, int *dataLen);
Int getData_Free(void *data);
Int getData_Free2(void **data); //避免野指针
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存

铁律7: 三级指针输出典型用法

三级指针做输出
int getFileAllLine(char ***content, int *pLine);
int getFileAllLine_Free(char ***content, int *pLine);
理解
主调函数还是被调用函数分配内存
被调用函数是在heap/stack上分配内存

铁律8:杂项,指针用法几点扩充

1)野指针 2种free形式
int getData(char **data, int *dataLen);
int getData_Free(void *data);
int getData_Free2(void **data);
2)2次调用
主调函数第一次调用被调用函数求长度;根据长度,分配内存,调用被调用函数。
3)返回值char */int/char **
4)C程序书写结构
商业软件,每一个出错的地方都要有日志,日志级别

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值