C语言指针学习记录
C语言指针学习记录
虚拟内存地址
在指针的学习之前,我们必须先了解内存,在我们设备的内存条中,有着自身的存储地址空间,操作系统将它的存储地址空间抽象成了一个巨大的一维数组空间,并且对于这个空间中的每一个字节都会分配一个编号,这个编号就叫做内存地址。
1 |
|
例如在上述代码当中,我声明了4个字符型的变量,并给他们赋了值,这时候,系统就会为他们分配空间来存放数据。假设当我们声明了这些变量之后,如果a的内存地址是101,那么下面b的就是102,以此类推,因为每个字符只占一个字节。那么如果里面存放的不是字符,而是整型呢?
我们知道,一个int类的整形占4个字节,那么在内存空间中的地址则是这样的:即每个int类的整形占了4个编号,也就是四个地址,但我们一般如果说y2的地址是多少?我们会说是它的首地址,也就是105
接下来实际操作一下:)
在上述代码中,我声明了4个字符型的变量,并给他们赋了值,接下来打印出他们的地址,(在变量名前面的”&”符号是取地址符,可以获得这个变量的地址, %p代表的是我们要输出地址类型的数据,就像%d是输出整数类型的数据一样)我们可以看到,这个地址是16进制的,每个字符只占了一个字节。
接着我们看这一段代码,我声明了2个int型的变量,并给它们赋了值,这时候让我们注意这两个地址的末尾,“8”和“C”,不就是相差了5吗,也就印证了我们之前的说法(一个int占5个字节)。
指针的含义
接下来就来到指针了。一般来讲,指针是用来存放内存地址的变量。也就是说,指针指向的就是一个变量的地址,创建一个指针变量就是在内存中分配了一块空间,通过指针就能找到这块空间的位置。
其实通俗地讲,指针就是地址,当我们声明一个指针变量时,也就是声明了一个存放地址的变量。
指针的创建与基本使用
指针的创建与赋值
1 |
|
在上述代码中,a是一个整形变量,当你声明了它之后,系统就会从内存中为它开辟一块空间,当你对a赋值的时候,是给这个空间中的数据赋值。但你不知道这个空间的位置(也就是地址);
b是一个指针变量(也可以叫做地址变量?),当你声明它之后,系统也会从内存中为它开辟一块空间,并且b代表的就是这个空间的位置(地址),当你对b赋值时,赋值的是一个地址,例如上述代码中,我把a的地址赋值给了b,这时候b的值就是a的地址。
让我们观看上面的运行代码,我们分别输出了a和b的地址和值,可以看到,b的值就跟我们上面说的一样,是a的地址,这也就是指针的作用之一
那么我们用指针b存放了a的地址,这时候,我们可以通过输出*b,来获得a的值,因为b中存放的是a的地址
ps: 当你创建了一个指针变量之后,输出&b是输出这个变量本身的地址,输出b是输出这个变量里面存放的地址,输出*b是到达这个变量里面存放的地址的空间,然后输出里面的值。
那么使用指针还有什么作用呢?拿上述的代码距离,我们可以通过修改*b的值,来改变我们定义的变量a的值,因为我们已经把a的地址存到了b里面了
间接引用操作符
当我们定义指针变量时,使用的是b,里面存放的是地址,当我们想要改变里面的地址时,我们是给b赋值(赋的是地址),而不是给*b赋值, 因为除了声明指针这一场景之外,其他地方的*b代表的是*指针变量里面存的地址指向的值,如下图所示,我们可以直接在定义int *b时给指针变量赋值,例如int *b = &a 也可以像下图一样给b赋值。
当我们使用printf输出*b时,因为现在b中存放的是a的地址,所以*b指的是a的地址里面存放的值,也就是变量a的值
这里我们可以得到指针的另一个作用,改变其他变量的值, 如下图所示,当我们将*b赋值为5时,同时变量a的值也会跟着变化
指针与数组
当我们获取一个数组的地址时,返回的是数组中第一个数据的地址
结构体与指针
结构体是一个或多个变量的集合,这些变量可以是不同的类型(跟java当中的类有点类似,只是没有类中的各种方法)
结构体的定义
1 |
|
1 |
|
结构体的初始化
1 |
|
1 |
|
简化结构体的初始化
当我们每次初始化结构体时,都要写struct,但我们可以在定义结构体时使用typedef关键字来解决
可以写成:
1 |
|
也可以写成: (为什么我们可以省略结构体名字呢?因为之后我们初始化结构体都是用的它的别名,不会用到结构体名字)
1 |
|
例如:
1 |
|
这时候的初始化: (没有前面的struct嘞)
1 |
|
声明结构体类型的指针
当我们定义了一个结构体,并声明(初始化)一个结构体指针, 那么我们如何给它里面的变量赋值呢?
如下面的代码,我们可以用(*t1).a = 1;来进行赋值
1 |
|
在C语言中,我们可以简写这一赋值方式,使用箭头进行赋值
1 |
|
动态分配内存
为什么我们需要动态分配内存呢?
平常我们写代码时,例如声明一个int a = 1;这时候系统会为我们这个变量自动分配一块空间,用完了不用之后自动给我们释放,我们自身不能控制什么时候给我们这个变量分配一块空间,什么时候释放这块空间,但有了动态分配内存,我们就能自己来决定什么时候分配和什么时候释放
在C语言中,我们会使用malloc函数来动态分配内存,使用free函数来释放内存
我们通过malloc分配内存空间,因为这里存的是int类型的数据,所以要在前面进行一次强制转换,这样就能给a指针变量分配一份4个字节的int类型的地址