指针
🌸🌸🌸关于指针学习是无止尽的,以下是我参照相关书籍,得到的一些体会,希望大家有所收获🌸🌸🌸
🚀🚀🚀大家觉不错的话,就恳求大家点点关注,点点小爱心,指点指点🚀🚀🚀
指针的定义:
首先,指针是变量,它和我们平常使用的整型变量、字符变量、浮点变量等各种变量并没有本质的差异,不同的只是它们的类型和值的含义,即解释方式。在二进制层面,指针的值就是内存单元的地址,而变量又是引用内存单元的值的别名,因此在语言层面指针的值就是变量的地址
注:只要我们始终掌握着对象的内存地址(也就是它的指针),我们就可以在任何地方对其指向的内存单元进行操作,无论是读写其数据还是调用其函数。这种灵活性正是指针危险(可能指向无效内存对象)和不易掌握的主要原因。如果你访问了非法的或无效的内存单元,就会导致运行时错误。
指针的类型:
指针的类型为一个类型名和字符“ * ” 的组合,我们平时说“一个int 类型的指针”,其实是在说“一个类型为 int*的指针”。编译器认为这样的一个指针指向的内存单元为4 字节,并将其内容解释为 int 类型的值。
注:虽然类型名和“ * ”的组合是一种指针类型,但是编译解释的时候,“ * ”是和其后的变量名结合的,例如:
int a,b,c;
编译器会理解为:
int a,b,c;
即只有a是int类型的指针,而b和c仍然是int类型变量
指针的运算:
全局指针变量的默认初始值是 NULL,而对于 non-static 局部指针变量 p,必须显式地指定其初值,否则p的初始值是不可预测的(不是NULL)。当你第一次使用它的时候就可能会用if(p !=NULL)来检查p 的有效性,然而此时if语句的确不起作用。如果你忘记了给p赋初值,那么你第一次使用p的时候就会导致运行时错误。
注:
不管指针变量是全局的还是局部的、静态的还是非静态的,应当在声明它的同时初始化它,要么赋子它一个有效的地址,要么赋予它 NULL
指针可以参与整数能够参与的任何算术运算,但是除了下列的运算外,其他运算都是没有实际意义。
(1)指针自增(++),表示它指向了序列中的后一个元素。
(2)指针自减(–),表示它指向了序列中的前一个元素。
(3)指针加一个正整数i,表示它向后递进i个元素。
(4)指针减一个正整数i,表示它向前递进i个元素。
(5)两个同类型指针相减,表示计算它们之间的元素个数。
(6)指针赋值,把一个指针值指派给另一个指针。
(7)指针比较(>,<,== ,!=,>=,<=),最常用的是==和!=。
(8)取地址(&)和解引用(*)。
注:
(1)当把“&” 用于指针时,就是在提取指针变量的地址。不能在一个指针前面连续使用多个“&”,例如&&p,因为&p已经不是一个变量了,不能把“&”单独用于一个非变量的东西。不能对字面常量使用“&”来取其地址,因为字面常量保存在符号表中,它们没有地址概念;
(2)当把“ * ”用于指针时,就是在提取指针所指向的变量.因此在“ * ”用于指针时一定要确保该指针指向一个有效的和合法的变量。不能对 void* 类型指针使用“*”来取其所指向的变量。
我们可以把函数的参数或返回值类型声明为指针类型。此时,函数接受的参数或返回值就是地址,而不是指针所指的内存单元的值
特殊类型的指针:
常量指针:
当为常量指针时,不可以通过修改所指向的变量的值,但是指针可以指向别的变量,就是指针变量的值是可以改变的。
int a = 5;
const int *p =&a;
*p = 20; //error 不可以通过修改所指向的变量的值
int b =20;
p = &b; //right 指针可以指向别的变量
指针常量:
当为指针常量时,指针常量的值不可以修改,就是不能指向别的变量,但是可以通过指针修改它所指向的变量
int a = 5;
int *const p = &a;
*p = 20; //right 可以修改所指向变量的值
int b = 10;
p = &b; //error 不可以指向别的变量
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。