我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。
这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。
C语言麻拐得很。
什么是变量?变量就是内存里面的一个东西,有值。
什么是“值传递”?C语言函数参数调用都是值传递,就是把变量的值给函数。
目录
函数参数究竟是什么
就是函数参数究竟是什么?这里面一个大坑。很多初学者对“值传递”、“传地址”很困惑,因为没人给他们解释“函数参数是函数内部定义的变量”,只不过必须在函数调用时给值而已,也就是赋初值。
(注:以下代码为示意,不严格)
int fun(int x)//这里定义了变量x
{
x=2;//这里操作变量x,跟函数调用的参数a没有任何关系
}
main()
{
int a=1;
fun(a);//这里复制a的值给x,相当于执行了x=a;当然实际汇编代码是push 1,效果一样的
}
因为参数就是函数里面的变量,操作这个变量和外部变量没有关系,所以修改参数不会影响外部变量。
强调:参数是函数内部变量,传参相当于给内部变量赋值
指针也是变量
什么是“指针”?内存的每个东西都有“地址”,存放地址的变量称为指针。
如果一个函数参数是指针,函数调用的时候发生了什么?
int fun(int * x)//这里定义了变量x,类型是指针
{
*x=2;//这里操作的是变量x里面的地址代表的内存,其实就是调用参数a
x=2;//这是一个BUG,2是一个非法地址
}
main()
{
int a=1;
int * b=&a;//为什么加这一句?因为本质上,&a就是生成了一个临时变量,类型为int*,值为a的地址
fun(b);//这里复制b的值给x,因为b的值是&a,相当于执行了x=&a;
}
&a不是地址传递,是生成临时变量
因为我们经常写“fun(&a)”这种代码,就觉得“&”表示了一种不同的传参方式,其实这是误解,这里的“&a”是一个运算,生成了一个临时变量,类型为“int*”,值为a的地址。
强调:只有值传递,没有地址传递
我们现在已经能够理解“只有值传递”这句话了,没有地址传递,地址只是变量的一种类型。函数能够修改外部数据是指针的妙处,不是传参的妙处。
C++和其他语言的“引用”、“参考”是什么
C++里面函数参数可以是“引用”,“引用”是什么?引用其实就是指针的另一种写法(当然严格讲引用和指针还是有不少区别的,但究其本质,就是一个语法糖)。
其它高级语言的“变量”、“对象”、“参考”、“引用”等等是什么?其实还是C语言的变量和指针,因为世界本来如此。包装再漂亮,也解决不了null异常。
代码实测
看看这个代码:
#include <iostream>
int f(int a)
{
a = 5;
std::cout << &a << " " << a << std::endl;
return a;
}
int main()
{
int a = 1;
std::cout << f(a) << std::endl;
std::cout << &a << " " << a << std::endl;
}
执行结果:
0000000B7775FAB0 5
5
0000000B7775FAD4 1
第一行是在函数f内输出的,输出的地址是函数的参数a的地址,第三行是在main函数里输出的,输出的地址是main函数的变量a的地址,很清楚,两个地址是不一样的。
我们再看看这个有点奇妙的代码:
#include <iostream>
void f(int * a)
{
a = 0;
std::cout << &a << " " << a << std::endl;
}
int main()
{
int a = 1;
f(&a);
std::cout << &a << " " << a << std::endl;
}
你可能会以为f里面给a赋值为0,外面的a就会变成0,看看实际输出:
0000008C212FF8D0 0000000000000000
0000008C212FF8F4 1
并没有。想想为什么。
(这里是结束)