指针和地址和引用
*&是取地址符号,是取内容符号。
在指针当中,这两个符号非常重要,当我们需要改变一个函数外部传入参数的值时,需要传入该变量的地址,而不是值。
找了很多解释,太过于艰深晦涩,对于初学者很不友好,
我觉得初期,就是要加快初学者对于概念的理解,
随着学习的深入,慢慢再去理解深层次的含义
找了很多资料,下面的解释我觉得通俗易懂,来自知乎
1.引用必须初始化,指针不用
2.引用初始化后不能被改变,指针可以改变所指对象
3.不存在指向空值的引用,但是存在指向空值的指针
可以参考下面博主的文章的学习
https://blog.csdn.net/Boooooots/article/details/88982272
引用就可以简单的理解为指针的别名,很多人也叫指针的小名,也就是内存地址
很多面向对象的语言,不用指针,而是用-引用,主要原因就是指针驾驭起来有些困难
而引用就安全很多,前面也说了,引用必须初始化
就可以直接理解,引用其实就是指针,就先这样记住就行
其实 指针就是地址
在进行定义的时候 int * p ,这里的P是指针变量,注意也就是指针类型的变量,想想整型变量,概念是一样的
p里面的值 只能存放地址,可以先这么理解
叫指针变量听起来并不形象,至少对于我们的语言并不好理解
pointer variable 指针变量,你结合英文去理解,就好理解多了,
point 就是指向,加er,动词就名词化了,clean-cleaner
所以pointer 指的就是指针
其实指针就是地址,我觉得你就当做地址变量,很多内容都很好理解了
“* p” : 其中“*” 就是Pointer “p”就是variable
int * p ; //定义指针变量p
int a = 10;//定义整型变量a,并赋值为10,等同于,int a; a = 10;
p = &a; //用-取地址符&-把a的地址取出来 赋给p
* p = a;
函数参数传递的三种方式
前置概念
形参:形式上的参数,用于展示函数要接收什么样数据类型的实参
实参:传递给函数所接收数据类型的实际数据
1.值传递
2.指针传递
3.引用传递
1值传递---------------------------------------------------------------------------------
//定义一个函数
void SwapValue(int x, int y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a = 3;
int b = 4;
SwapValue(a, b);//在调用这个函数的时候,里面隐含了一句 x = a, y = b
return 0;
}
这个过程,其实只是把a和b 的值传递给了 x 和y,
最后并没有改变 a 和 b的值
2指针(地址)传递---------------------------------------------------------------------------------
//定义一个函数
//这里形参的x和y 都是指针变量
void SwapPointer(int * x, int * y)
{
int temp = * x;
* x = * y;
* y = temp;
}
int main()
{
int a = 3;
int b = 4;
SwapPointer(&a, &b);//在调用这个函数的时候,里面隐含了一句 x = &a, y = &b
return 0;
}
2引用传递---------------------------------------------------------------------------------
//定义一个函数
//这里的形参x和y 都是引用变量类型
void SwapReference(int & x, int & y)
{
int temp = x;
x = y;
y = temp;
}
int main()
{
int a = 3;
int b = 4;
SwapReference(a, b);//在调用这个函数的时候,里面隐含了一句 &x = a, &y = b
//也就是x是a的引用,y是b的引用,也就是别名,小名,一堆名,引用必须初始化,否则报错
return 0;
}
引用即对象的别名,传对象的引用,用于把一个对象的地址作为参数传递给形参,而不是对象本身。引用传递,避免了一次实参到形参的拷贝,提高了效率
使用场景
1.如果数据对象较小,如内置数据类型或小型结构,则按值传递
2.如果数据对象是数组,则使用指针,并将指针声明为指向const的指针
3.如果数据对象是较大的结构,则使用const指针或const引用,以提高运行效率,以减少复制结构所需要的时间和空间
4.如果数据对象是类对象,则使用const引用,传递类对象参数的标准方式是按引用传递。
其他
学习C语言和C++这些内容,有助于理解
C# 中的委托,以及C#中提到的引用
其实这些内容都是相通的
函数指针和指针函数,对象的概念
指针与数组
***指针
int p p是个变量名字, int 表示该P变量只能存储Int类型变量的地址
* 就是指针 指向P变量里存储的值(这个值是内存地址)
int i = 10
p = &i
那么 p = i 也就是说p 就是i 本身
定义
地址:内存单元的编号,
从0开始的非负整数,
范围: 0 – FFFFFFFF【0~4G-1】
指针:指针就是地址,地址就是指针
指针变量是存放内存单元地址的变量
指针的本质是一个操作受限的非负整数
总结:
1.如果一个指针变量(假定为P)存放了某个普通变量(假定为i)的内存地址
那么我们就可以说“p指向了i”,但是P与i 是两个不同的变量
修改p的值不影响i的值,修改i的值也不影响P 的值
2.p 等价于i 或者说p 可以与 i 在任何地方互换
3.如果一个指针指向了某个普通变量,则
指针变量 就完全等价于 该普通变量
注意:
指针变量也是变量,只不过它存放的不能是内存单元的内容,只能存放内存单元的地址
普通变量前不能加
常量和表达式前不能加&
如何通过被调函数修改主调函数中普通变量的值
1.实参为相关变量的地址
2.形参为以该变量的类型为类型的指针变量
3.在被调函数中通过 * + 指针变量名 的方式就可以修改主函数中的变量值-
#include <stdio.h>
void f(int* p)//不是定义了一个名字叫做*p的形参, 而是定义了一个形参,该形参的名字叫做p,它的类型是 int *。是一个指针变量
{//也就是传进来的形参是一个内存地址,int*是一种类型
*p = 100;
}
int main(void)
{
int i = 9;
f(&i);
printf("%d\n", i);
}
#include <stdio.h>
int main(void)
{
int a[5] = { 1,2,3,4,5 };
a[3] == *(a + 3); //这个也是等价的,a代表的是数组的首地址-内存地址
printf("%p\n", a+1 );
printf("%p\n", a );
printf("%d\n", *(a + 1));// *a 就等价于a[0],也就是说a代表的是第一个数据的地址变量,a=&a[0]
}