1.指针的理解
2.解引用
3.指针变量的大小
4.指针的类型
5.const修饰变量
注:下文如若不做说明,均是在32位环境下。
1.指针的理解
#指针就是地址,地址就是指针。存放地址(或指针)的变量就是指针变量。
#我们用一个具体的例子来说明一下:
int main()
{
int a=10;
int* p=&a;
return 0;
}
变量p就是指针变量,它的类型是int*,又可以理解为是存放int类型地址的类型,指向int(存放的谁的地址就指向谁)。
int** pp=&p;
这里pp指向p(int*类型),pp的变量类型为int**。
#所有指针的大小都是4/8个字节(32位或64位)。
2.解引用
我们还是以上面的例子来看:
int main()
{
int a=10;
int* p=&a;
return 0;
}
在 int* p=&a; 中,*是为了说明p是一个指针;而在 int** pp=&p; 中,*是为了说明pp是一个int**的指针。
*也可以是一个操作符,是解引用操作符。变量p存放着a的地址,我们对p解引用,就可以访问a的内存空间。
eg:*p==10;
实际上,解引用和取地址操作是互逆的运算,二者共同运算时,会相互抵消。
eg:*&p==p;
3.指针变量的大小
#取决于你的机器是32位还是64位。
4.指针的类型
这个知识点是重点。
先来看几个例子:
int* p1 ->大小是四个字节,解引用访问四个字节;
char* p2 ->大小是四个字节,解引用访问一个字节;
我们也知道指针加减整数。对于以上两个例子有:
p1+1 -> 跳过四个字节,
p2+1 -> 跳过一个字节。
从以上的举例中可以得知,指针类型具有丰富的意义。
#1.决定了解引用访问多大的空间;
#2.决定了指针的步长(+1或-1跳过几个字节);
#3.决定了解引用访问的是什么类型的变量(如int,int*等);
同样,指针的类型也可以用于强转中,比如:
想让int*访问一个字节,可以强转为char*;
低地址 高地址
——————————————————>
1 2 3 4
(表示编号,下同)
如图为以上int的数据,每一个方格代表一个字节;
每一个字节有一个对应的地址编号。那这里第一个问题出现了:一个int* 只能放一个地址,而它又是指向整个整型,那它究竟放的是那个字节的地址呢?
结果:是最低地址的字节的地址。对于其他数据类型(如short,float,double等)都适用。
我们进行强转之后,只是改变了它的类型,但没有改变它存放的值(地址),所以解引用之后,只访问第一个字节。
上述的例子是大转小,那么小转大呢?
#我们就试着转成一个double类型。众所周知的是,double类型的大小是8个字节,所以我们需要再开辟4个字节以保证不会越界访问。
低地址 高地址
————————————————————>
1 2 3 4 5 6 7 8
上文的 int* 存放的是1号字节的地址,当我们强转成double类型时,它(指针)就认为从1号字节往后到8号字节共8个字节都是它所指向的一个double类型,所以当对其解引用时,它会直接从最左边向后访问8个字节。
#泛型指针
void*,无类型,可以用来接收任意类型的指针;
但不可以解引用和进行整数的相加减。
那到底有什么用呢?
#通常:别人要给你传一个未知类型的指针,可以用 void* 来接收。当我们确定它的具体类型时,进行一下强转就可以了。
好了,关于指针的类型我们就讲到这里~
5.const指针
5.1 const修饰变量
我们先用一个例子来引入:
C语言中有几种变量类型,如int,float,那它们为什么叫变量呢?
#是因为它们可以被修改。如:int a=10; 我也可以通过赋值把它改成20,这就是可修改。
同样,常量就不可以被修改,如:3=5;这种操作就是非法的,因为3是个常量。
#当我们在上述例子的前面加上const时——>const int a=10; ,这时我们再去修改,会发现编译系统报错了,提示你a不可被修改。这里变量a就被赋予了常属性。
当然,这里的a还是一个变量,那么如何验证呢?
eg:int arr[a]={0};
然后我们运行一下,就会发现问题。说明a还是一个变量(但在C++中就是常量)。
这里又出现一个问题:直接修改不可以,那能不能间接修改,比如指针呢?
eg:int* p=&n;
*p=20;
我们发现此方法可行。但这样的方式有问题。const本来就是为了保护变量不被修改,但却被指针通过间接的方式给修改了。所以,引出我们第二部分的问题。
5.2 const修饰指针
要想真正做到保护变量,要从指针入手。
(1)const放在*的左边
eg:int main()
{
int a=10;
const int* p=&a;
}
放在左边,限制的是 *p ,也就是变量本身,但不限制p;
#即不能改变变量的值,但可以改变所指的对象;
(2)const放在*的右边
还是以上面的例子为例。
int main()
{
int a=10;
int* const p=&a;
}
放在右边,限制的是p,不限制 *p ;
#即不能改变所指向的对象,但可以改变变量的值。
今天就先到这里吧,真写累了,对文章内容有异议的宝子在评论区留言哈~