type
status
date
slug
summary
tags
category
icon
password
指针,C语言的核心
📝 主旨内容
指针变量声明的一般形式:type *var_name;
1.定义
int* p = &a
*
是解引用操作符,意思是通过p
中存放的地址,找到p
所指向的对象,*p
或者说a
就是p
指向的对象。*
说明p
是指针变量,int
说明p
指向的对象a
是int
类型。指针就是内存单元的地址,也就是内存单元的编号。var
变量的地址: 0x7ffeeef168d8
ip
变量中存储的地址: 0x7ffeeef168d8
*ip
变量的值: 202.指针使用示例
先看下面这样一个错误范例
我们发现,问题在于:实参a和b传给形参x和y后,形参是实参的一份临时拷贝,形参也有自己的独立空间,因此对形参的修改不会影响实参。
正确做法:
3.一些关于指针的结论:
3.1指针结论的推导
公理:1.指针也就是内存地址,指针变量是用来存放内存地址的变量。2.取地址里面的值的第一种方式:地址[i]3.取地址里面的值的第二种方式:*地址
在绝大多数关于数组的表达式中,数组名代表指针常量,这个指针指向数组首个元素。
从数值上讲,数组名表示的值就是首个元素的地址。 因此:
arr=&arr[0]
另外我们还知道:
arr+i
指针+1 并不是指针代表的地址值+1。 指针变量加1,即向后移动1 个位置,表示指针变量指向下一个数据元素的首地址。而不是在原地址基础上加1。至于真实的地址加了多少,要看原来指针指向的数据类型是什么。 例如:char
型,右移1个字节;int
型,右移4个字节。 这些操作是由编译器来完成的。所以,指针必须指向某个类型,这样编译器才能知道指针每次加1时真正内存的步长是多少。
那么我们可以很轻易地推导出:
arr[i]=*(arr+i)
这也吻合了为什么数组下标从0开始:为了保证指针运算与数组下标统一。
更进一步,我们可以得出类似下面这样形式的结论:
(arr+1)[2] = arr[3] = *(arr+3)
另外,由于arr+i表示元素位置的偏移,arr+i得到的也是一个指针(地址)。那么我们也可以易知,指针是可以相减的,指针-指针得到的是指针和指针之间相差的个数(不是所有的指针都能相减,指向同一块空间的2个指针才能相减)。即:
&arr[m]-&arr[n] = m-n
- 此外,我们还要区分
arr+1
和&arr+1
&arr+1 | arr+1 =&arr[0]+1 |
&arr 是指向整个数组的指针,取出的是整个数组的地址。因此,如果我们将&arr 移动1个位置,它将移动一整个数组的地址,指向下一个包含5个元素的块。 | arr 是指向数组第一个元素的指针。因此,如果我们将arr 移动1个位置,它将指向第二个元素。 |
如果数组基地址为 00D5F940 ,则&arr+1 将为00D5F940+(5*4) ,即00D5F954 | 如果数组基地址是 00D5F940 ,则arr+1 将是00D5F940+4 ,即00D5F944 |
- 区分
*p++
和(*p)++
p++
的意思是对p解引用后,再P+=1
(*p)++
的意思是对p
解引用后的值+1
3.2练习
不用strlen()函数,计算字符串长度
4.指针变量的大小
- 不管是什么类型的指针,都是在创建指针变量。 指针变量是用来存放地址的。 指针变量的大小取决于一个地址存放的时候需要多大空间。 对于32位的机器,假设有32根地址线,那么假设每根地址线在寻址的时候产生高电平(高电压)和低电平(低电压)就是(1或者0); 那么32根地址线产生的地址就会是:2^32 每个地址标识一个字节,那我们就可以给(2^32Byte==2^32/1024KB== 2^32/1024/1024MB=2^32/1024/1024/1024GB==4GB)4G的空闲进行编址。
- 在32位的机器上,地址是32个0或者1组成二进制序列,那地址就得用4个字节(4byte=32bit)的空间来存储,所以一个指针变量的大小就应该是4个字节。
- 那如果在64位机器上,如果有64个地址线,那一个指针变量的大小是8个字节,才能存放一个地址。即: 32位机器上的地址:32bit位 - 4byte,所以指针变量的大小是4个字节 64位机器上的地址:64bit位 - 8byte,所以指针变量的大小是8个字节
这里我们就明白:
- 作者:江牧
- 链接:https://lawyerjiang.top/article/key/c/2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章