1:传值和传址区别
按值传递:
- 在调用函数中将原函数的值拷贝一份过去给被调用的函数,在被调用函数中对该值的修改,不会影响原函数的值。
- 值传递,变量赋值,修改变量的值------修改的是新地址(复制地址)的内容,并不会影响到原来地址的数据。
- 在函数调用中,形参是实参内容的拷贝,并不是地址的拷贝,所以改变形参的值,并会影响实参的值。
按地址传递:
- 在调用函数的时候将原函数的值所在的地址拷贝一份过去,被调用函数对这个地址所作的修改会影响原理的值。
- 地址传递:用指针修改变量的值,就是把原地址中的值修改了,就相当于对实参本身进行的操作。
1.1:概述:变量的地址和地址中的内容
首先我们要知道:变量a的地址和 变量a地址中的内容的区别,数据是存放在内存中的,每一个变量都有一个内存地址,变量的内容存放在对应内存地址的空间中。
如:定义 :
int a = 10 ;
那么a在内存中的地址是 ox1100 , 在这个地址中存储的数据就是 10 。
假设创建指针 p ,把a的地址赋值给 p ,就是把 a的首地址 ox1100 赋值给 指针p ,这个时候p的值就是变量a在内存中的首地址。
int a = 10;
int *p;
p = &a;
1.2 :案例:值传递
新开辟一个内存空间,存储原理变量的值,修改变量修改的是新内存空间中的值,所以,原始的参数是不会被函数修改的。
优点: 通过值传递传的参数可以是内置类型参数:数字,字符等。原本参数的值是不会被修改的。
缺点:不能修改原参数的值。
#include<iostring>
#include<string>
uising namespace std;
void swap(int x, int y) {
int temp;
temp = x;
x = y;
y = temp;
}
int main(){
int a = 4, b = 6;
printf("交换前:n a = %d, b = %d\n", a , b);
swap(a,b);
printf("交换后:n a = %d, b = %d\n", a , b);
return 0;
}
1.3: 址传递
址传递:就是指针传递,形参实际是指向实参地址的指针,当对形参进行操作时,就相当于对实参本身进行操作。
可以改变指针指向内容的值,但是不能改变指针本身的地址。
#include<iostream>
#include<string>
using nameapace std;
void swap(int* x, int* y) {
int temp = *x;
*x = *y;
*y = temp;
}
int main(){
int a = 4,b = 6;
printf("交换前:a = %d ,b = %d", a, b);
swap(&a, &b);
printf("交换后:a = %d ,b = %d", a, b);
}
1.4:案例:面试题 :看下面面试题
#include<iostream>
#include<string>
using namespace std;
void getMemory(char* p) {
p = (char*) malloc(100);
}
int main(){
char* str = NULL;
getMemory(str);
// 运行会报错:程序会崩溃,没有输出(因为str 始终是 NULL)
strccpy(str, "hello wodl");
printf(str);
}
- 解析:函数getMemory() 并不能动态传递内存,main函数中的 str 一直是 NULL,strcpy(str, "hello world" ); 将使程序崩溃,无法输出。
- 其实函数getMemory()的形参p 是实参数str的一份拷贝,函数中的操作都是针对 p指向的内存地址进行的,实参之前 指向的内存地址是NULL, 后面仍然是 NULL ,所以输出 *str的值就会产生崩溃
解决方案
- 如要要解决上述问题:我们可以将形参从 一重指针修改为 二重指针。
- “二重指针指向一重指针的地址”: 也就是说:传递过来的即使就是 *str本身
#include<iostream>
#include<string>
using namespace std;
void getMemory(char** p) {
p = (char*) malloc(100);
}
int main(){
char* str = NULL;
getMemory(str);
// 运行会报错:程序会崩溃,没有输出(因为str 始终是 NULL)
strccpy(str, "hello wodl");
printf(str);
}