## 一:
-
代码:
#include <stdio.h>
#include <stdlib.h>
int Add(int a,int b){
int c = a + b;
return c;
}
int main(){
int x = 2, y = 4;
int z = Add(x,y);
printf("Sum = %d\n",z);
}
输出结果:
Sum = 6
-
x ,y ,z都是main函数的局部变量,a , b, c是Add函数的局部变量
-
当调用Add函数时,main函数中的x的值拷贝给函数Add的a,y的值拷贝给函数Add的b
-
函数形参只传值,不传址,用&才传址
#include <stdio.h>
#include <stdlib.h>
int Add(int a,int b){
printf("Address of a in Add = %d\n",&a);
int c = a + b;
return c;
}
int main(){
int a = 2, b = 4;
printf("Address of a in main = %d\n",&a);
int c = Add(a,b);
printf("Sum = %d\n",c);
}
输出结果:
Address of a in main = 6487572
Address of a in Add = 6487536
Sum = 6
可以发现两个a的地址是不同的,他们存放在不同的地址中
-
main函数称为“主调函数”,Add函数被称为“被调函数”
二:
把main函数中a,b的地址传给Add函数
#include <stdio.h>
#include <stdlib.h>
int Add(int* a,int* b){//a,b在Add中是整型的指针变量
printf("Address of a in Add = %d\n",&a);//会打印出指针变量
printf("Value in a of Add (address of a of main) = %d\n",a);//会打印出main中a的地址
printf("Value at address stored in a of Add = %d\n",*a);//会打印main中a的值
int c = *a + *b;//通过*来访问这些地址的内容
return c;
}
int main(){
int a = 2, b = 4;
printf("Address of a in main = %d\n",&a);
int c = Add(&a,&b);
printf("Sum = %d\n",c);
}
输出结果
Address of a in main = 6487576
Address of a in Add = 6487536
Value in a of Add (address of a of main) = 6487576
Value at address stored in a of Add = 2
Sum = 6
-
从这个函数返回一个整型指针:
#include <stdio.h>
#include <stdlib.h>
int* Add(int* a,int* b){//我们对Add函数所做的修改是返回一个整型指针
int c = *a + *b;
return &c;//返回c的地址
}
int main(){
int a = 2, b = 4;
int* ptr = Add(&a,&b);//要接收返回的地址,所以需要定义一个指针变量
printf("Sum = %d\n",*ptr);//打印这个指针地址的值
}
输出结果:
Sum = 6
这个代码存在问题
ptr保存了c的地址,但c作为子函数的局部变量,已经在栈中被消除了,找不到这个地址的
-
增加一个PrintHelloWorld函数
#include <stdio.h>
#include <stdlib.h>
void PrintHelloWorld(){
printf("Hello World\n");
}
int *Add(int* a,int* b){
int c = *a + *b;
return &c;
}
int main(){
int a = 2, b = 4;
int* ptr = Add(&a,&b);
PrintHelloWorld();//在打印Sum前先调用函数PrintHelloWorld
printf("Sum = %d\n",*ptr);
}
输出:
Hello World
Sum = 0
输出有问题
原因:执行到函数PrintHelloWorld时,现在需要为PrintHelloWorld分配栈空间,因为之前没调用打印PrintHelloWorld, 就不会在栈上分配空间,main上面栈帧没改变,调用后改变了。Add函数的栈帧在main函数的上面,调用完以后,他的局部变量消失了
-
什么情况下我们回想从函数返回一个指针:如果我们在堆(heap)上有一个内存地址或者在全局区(global)有个变量,我们就可以安全的返回他们的地址
-
#include <stdio.h>
#include <stdlib.h>
void PrintHelloWorld(){
printf("Hello World\n");
}
int *Add(int* a,int* b){
int* c = (int*)malloc(sizeof(int));//使用malloc从堆上分配一些空间(malloc是一个库函数,返回一个指针
*c = *a + *b;//把*a + *b赋给这个指针所指向的内存空间
return c;//返回地址c(返回的是堆上的地址,是可以的)
}
int main(){
int a = 2, b = 4;
int* ptr = Add(&a,&b);
PrintHelloWorld();
printf("Sum = %d\n",*ptr);
}
输出:正常
Hello World
Sum = 6
-
函数返回指针时,我们必须保证地址没有被重用(用来存储其他东西),以及那个地址的数据没有被清除
函数指针
可以用来储存函数的地址,此指针指向函数,我们可以用这样的指针来引用和执行函数。
函数指针储存函数的地址就是说,函数指针存放在了函数在内存中的起始地点或者说入口点
#include <stdio.h>
#include <stdlib.h>
int Add(int a, int b) {
return a+b;
}
int main(){
int c;
int (*p)(int,int);//创建一个指针指向这个函数Add
p = &Add;//填入函数的地址
//把Add的地址赋给p ,通过p我们就可以执行函数Add
c = (*p)(2,3); //传入两个整型变量2和3
printf("%d",c);
}
输出:
5
-
函数指针中声明的参数类型,要和所指向的这个函数的类型一致。所以指向函数的指针应该将(int,int)作为参数并返回int
int (*p)(int,int);
-
这里首先使用*操作符解引用来获得这个函数,然后把2个参数传给这个函数
c = (*p)(2,3);
-
如果不使用括号把指针变量名括起来,就表示的是声明了一个函数,这个函数返回一个整型指针
int *p(int,int);
-
这是在声明一个函数,它返回一个整型指针
int *Func(int,int);
-
加上括号就是在声明一个函数指针
int *(Func)(int,int);
-
有两种方式引用和解引用
p = Add;//不使用&,它的含义也一样,只使用函数名也会返回函数的地址
c = p(2,3);//解引用时,也可以直接使用函数指针名
-
为了指向一个函数,函数的指针类型必须是正确的
void (*p)(int,int);//这样p就不能指向函数Add,从而产生编译错误
#include <stdio.h>
void PrintHello(char *name){
printf("Hello %s\n",name);
}
int main(){
void (*ptr)(char*);
ptr = PrintHello;
ptr("Tom");//双引号也是一种指针,是指针常量,指向常量区的字符串,值等于字符串的地址
}