C语言基础级——指针定义(1)
文章目录
C语言指针,这部分应该是C语言的核心,也是较为复杂的知识,想要学懂并灵活运用起来,对于小白来说要去慢慢的啃。推荐一本书籍《C和指针》,这本书融合了指针与数组、函数、字符串等等,网上有很多电子版本,可以自己去搜检。或者如果大家有需要,可以私信我~~~
指针内容比较多,所以分为几部分,展示给大家,这些我会陆陆续续更新。
- 指针定义
- 指针数组、数组指针
- 字符串指针
- 指针函数、函数指针
- 指针、数组、函数
- 结构体指针
- 指针、结构体、函数
本节内容主要讲解指针的各个运算符的含义,以及如何普通数据类型与指针数据类型大小为何不同。
1 取址符:&
1.1 普通变量取址
先实现输出变量值,然后输出变量所在的地址。第二部分¶m
它的意思是取出param
变量的地址,并通过printf
打印其地址。
int param = 5;
// 打印param的变量值与地址
printf("%d %p\n", param, ¶m);
1.1.1 图解:
别名:给 0x7ffff09f67cf4 地址取个名字叫param
,param
空间存放的是int
类型的内容。¶m
就是该空间的地址(0x7ffff09f67cf4),我们就可以通过这个方式查找到param
变量在内存当中的地址,&
是地址运算符。
(这里的输出地址每一次执行都是会变化的)
1.1.2 地址运算符和位运算符区别
&
运算符符号,其实在取址和位运算当中,一个是单目运算符,另一个是双目运算符。
- 取址
&
代表的是取地址符。
int a = 5;
printf("%d\n", &a);
- 位运算
&
代表的是完成与运算。
int a = 5;
int b = 5;
printf("%d\n", a & b);
注意:
两种写法是等价的。
int num = 5;
int *ptr;
// 这两个也是等价的
ptr = #
ptr = & num;
2. 指针变量
// 定义一个指针变量ptr
int *ptr;
// 定义一个普通变量
int param = 5;
// ptr指针变量空间存放param的地址
ptr = ¶m;
- 把
ptr
当作变量来看,那我们知道¶m
是取普通变量本身的地址。
// 输出param的内存地址
printf("¶m addr = %p\n", ¶m);
&ptr
就是取指针变量本身所在的地址。
// 输出ptr的内存地址
printf("&ptr addr = %p\n", &ptr);
ptr = ¶m
,ptr
指针指向param
地址。或者可以理解为指针变量ptr
,本质上它也是一个变量,只是它存放的是param
普通变量的地址;
// 输出ptr所保存的地址
printf("ptr addr = %p\n", ptr);
把上述整合一起:
#include<stdio.h>
int main()
{
// 定义一个指针变量ptr
int *ptr;
// 定义一个普通变量
int param = 5;
// ptr指针变量空间存放param的地址
ptr = ¶m;
// 输出param的内存地址
printf("¶m addr = %p\n", ¶m);
// 输出ptr的内存地址
printf("&ptr addr = %p\n", &ptr);
// 输出ptr所保存的地址
printf("ptr addr = %p\n", ptr);
return 0;
}
2.1 间接运算符:*
*ptr
的作用是,通过存放在内部的地址(0x7ffdd2d2fb1c),查找到这个地址(0x7ffdd2d2fb1c)里面所存放的值(2)。这个过程其实相当于通过*ptr
间接的取出里面的值。(从param也能直接取出里面所存放的值)。
注意:
- 间接运算符
*
和 数学相乘运算符*
它们不要混淆一起。 - 两种写法是等价的。
// 等价
int *ptr;
int* ptr;
3. 声明数据类型
简单回顾一下,各个数据类型各占内存空间大小。
#include<stdio.h>
int main()
{
// 打印各个数据类型所占的字节数
printf("int = %ld\n", sizeof(int));
printf("char = %ld\n", sizeof(char));
printf("float = %ld\n", sizeof(float));
printf("double = %ld\n", sizeof(double));
return 0;
}
那么不同类型的指针变量是否也和上述的一致呢?一起来先看下实验测试。
#include<stdio.h>
int main()
{
printf("int* = %ld\n", sizeof(int*));
printf("char* = %ld\n", sizeof(char*));
printf("float* = %ld\n", sizeof(float*));
printf("double* = %ld\n", sizeof(double*));
return 0;
}
实验证明出结果并不一致,与我们猜想完全不一样。这是为什么呢?其实,这和我刚开篇说提到的指针特性有关,C语言指针内部用来存放地址。 地址字节数和系统的位数有关,系统和编译器为64位,那地址空间大小占8个字节;如果系统和编译器为32位,那地址空间大小占4个字节。所以我们先认清楚第一个,指针变量所占的字节数和系统的位数有关系的。
那么接下来我们会产生两个疑问,第一个是指针变量前面的数据类型有什么作用呢?第二个是指针变量本身空间又是什么类型?
int* ptr
,它代表的是当前的指针ptr
所指向的值*ptr
的为int
类型,也就是param
存放的数据类型。
int param = 5;
int *ptr;
ptr = ¶m;
*ptr
本身存放空间的是地址,那这段空间地址是为空数据类型(也就是void*
),它既不是int*
也不是char*
,大多数的系统当中,内存地址数据类型都是用空数据类型来表示的。
注意:
int param = 5;
// 两者等价的
int *ptr = ¶m;
int *ptr;
ptr = ¶m;
这两者也是等价的,大家对这个等价关系也会产生疑问吧?如何去解释?
-
第一种解释:
-
第四行:给
*ptr
分配了四个字节空间(0x7ffdd2d2fb20)的同时,在空间内存放地址(0x7ffdd2d2fb1c)。
-
第七行:先给
*ptr
分配四个字节空间(0x7ffdd2d2fb20),完成此步骤后,再给*ptr
空间内存放param
地址(0x7ffdd2d2fb1c)。
-
-
第二种解释:
普通变量表示:
int param = 5;
int ptr = 5;
int ptr;
ptr = 5;
再变换:
int param = 5;
int ptr = ¶m;
int ptr;
ptr = ¶m;
最后变化:
把int *ptr
转换成 int* ptr
,我们有说过指针变量本质上是一个变量。
int param = 5;
// 两者等价的
(int*) ptr = ¶m;
(int*) ptr;
ptr = ¶m;