目录
指针!!!
指针简介
计算机的存储机制
定义指针
指针的操作
& 取地址
* 取内容
数组与指针
逐一打印数组元素
数组就是指针
数组名就是指针变量
注意事项
错误示范:
1.定义了指针不赋初值,直接引用指针变量
2.同级指针之间才能相互赋值
本篇博客为C语言学习笔记,学习视频链接:
[C语言] 指针的详解与应用-理论结合实践,真正理解指针!
指针简介
- 指针(pointer)是C语言的一个重要知识点,其使用灵活,功能强大,是C语言的灵魂。
- 指针?什么是指针?从根本上看,指针是是一个值为内存地址的变量(或数据对象)。指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问。
指针和内存是离不开的,先了解一下内存是怎么定义的。
- 内存的框图如上,计算机通常把内存分配成上图模式的线性空间
- 内存分为一个个线性的区域,每个线性区域,都是一个字节为单位的,线性分配下去
- 每个字节都对应一个地址(独一无二的地址)
int a = 0x12345678; //0x是十六进制前缀,后面是实际的数据
short b = 0x5A6B;
char c[] = {0x33,0x34,0x35};
在计算机系统里,int类型变量,代表4个字节数据,4*8 = 32个二进制数来表示,就是32位,但是要注意在51单片机里,int类型是16位的。
int a = 0x12345678; 这样定义一个int类型的变量,变量名称为a,把它分开成四个字节来看
0x12 | 34 | 56 | 78
如上图内存的分配可以看到,0x78存储在0x4000地址,0x56存储在0x4001地址,0x34存储在0x4002地址,0x12存储在0x4003地址,总共占用四个字节。
数据的小端(低位)存储在内存地址的低位,就是把小端存在前面,这种分配方式叫小端模式。
另一种存储模式叫大端模式:数据的大端(高位)存储在地址的低位。
现在的计算机普遍运用小端模式分配地址。
short类型的变量当然也是小端模式存储。
char类型的数组,就是按照顺序存储,对照上图。数组在内存中分配的是连续的内存空间。
那如果是short类型的数组呢?
举个例子,short d[] = {0x5A6B, 0X7C8D};
那么存储方式应该是先给数组开辟一段连续的地址,然后按照数组的顺序依次分配地址,数组内地每一个数据都是小端模式 :第0位放在地址低位……
地址 内存
0x4009 0x6B
0x400A 0x5A
0x400B 0x8D
0x400C 0x7C
定义指针
- 指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。
- 定义一个指针变量:
指针变量的x字节,起码要存的下这个数据,所以不同系统,指针的位宽用不同的长度
用示例演示一下
可以看到我定义的指针位宽是4个字节,我猜是因为vscode调用 gcc编译器是32位的,所以指针p位宽是4,在Dev-C++里运行,针p位宽是8
指针的操作
& 取地址
- 若已定义:
int a; //定义一个int型的数据
int *p; //定义一个指向int型数据的指针- 则对指针p有如下操作方式:
- 如果&运算符左右都有变量,那么这个符号就代表位运算&;
- 如果&运算符只有右边是变量,那个就代表取地址的意思
- 如果*运算符左右都有变量,那么这个符号就代表乘法运算符;
- int *中的*只是一个标识,一个代号
- 如果* 只有后面有变量,而前面没有数据类型,那就是取内容,就是解引用的意思
此时想到狄泰软件学院唐老师说的:“编译运行试试就知道了呗,反正电脑又不会爆炸 !”
用示例说话~
运行结果的第一行是打印a这个变量
第二行是取出a的地址
第三行是取出指针变量p指向德内容a (p取了a的地址,代表p指向a,引用p,就是引用a)(地址间接访问数据)
指针变量的运算一般只有“+”和“-”,没有“”或“/”或乘方开方等等,因为它只是个地址
由p++运算 可以看到,p的地址加了一个char类型的数据宽度1,如果改为int类型的变量会怎么样呢?
可以看到地址加了4(int型变量的数据宽度就是4)
因为指针越界了,指向了非法的位置,出现了不可预知的错误,所以我才给注释掉~~~
指针的++或--一般用在数组里边,对于这种单独的变量就是做一个演示。
数组与指针
数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于 申请内存、定义指针和初始化
例如: char c[] = {0x33, 0x34, 0x35};
等效于: 申请内存
定义char *c = 0x4000;
初始化数组数据
利用下标引用数据也等效于指针取内容
c[0]; 等效于:*c;
c[1]; 等效于:*c+1;
c[2]; 等效于:*c+2;
之前是习惯了用for循环打印数组
现在就可以用指针了
定义一个指针变量p,变量p++就相当于数组下标加加
数组取下标就是指针取内容的另一种表示形态
数组a本身就是一个指针
如果将数组类型转换为int类型,效果也是一样的~
因为int类型的变量占4个字节,所以指针每次加1,都会跳4格,但是实际访问数据就是依次访问的(根据变量类型宽度而定)
上文提到了申请数组的等效方法:
- 申请内存
- 定义char *c = 0x4000;
- 初始化数组数据
申请内存需要用到 #include
malloc(3*4); //申请内存 3个变量*4个字节 返回值是void*
//void*是空* void*可以表示任何类型的指针定义指针 int *a;
a = malloc(3 * 4); //定义
然后初始化数据
*a = 0x38;
*(a + 1) = 0x32;
*(a + 2) = 0x35;
这种申请内存的方法,还是第一次接触呢~
数组就是指针 数组名就是指针变量注意事项
- 在对指针取内容之前,一定要确保指针指在了合法的地址,否则将会导致程序出现不可预知的错误
- 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告
数组是有越界的,数组越界和指针指向了非法位置是一样的性质
因为数组就是指针,那指针也可以越界的说法
错误示范: 1.定义了指针不赋初值,直接引用指针变量举个栗子
只有定义但是没有赋初值,运行出错了
0x55是随意赋的地址,地址是非法的,所以运行不出来
赋初值就可以运行了
2.同级指针之间才能相互赋值变量看做零级指针
普通的指针就看做一级指针
指针再取地址就是二级指针
指针级别不同造成的错误:
有个警告,从int*类型赋值给int类型,没有进行强制转换
如果是 p = a; 也是不可以的
a = *p; 对p取内容,他们就变成同级指针了,就可以赋值了
p = &a; 对a取地址,也变成同级指针
有关指针的原理,目前就学了这么多!
初级指针
二级指针,函数指针,结构体指针……这些复杂的指针,暂时用不到~_~
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
当前名称:【C语言】指针的理论详解-创新互联
链接URL:http://lswzjz.com/article/cedhgi.html