1. 函数与指针
一个函数在编译以后会占用一定的内存,在c语言中函数一般是在栈里面,而函数名就是函数在栈中的首地址。那么接下来会讲解如何通过指针调用函数呢?用指针调用函数我们称为函数指针,指针作为一种数据类型,它指向或引用内存中的数据,那么指针同样可以用来存储函数地址(起始地址),从而可以通过指针来解引用和执行函数。
我们用这段代码来讲解
#include<stdio.h>
void PrintHello(char *name){
printf("Hello %s\n",name);
}
int add( int a, int b)
{
return a+b;
}
int main(){
int c;
int (*p)(int,int); //声明函数指针,括号里面的变量类型必须要和函数保持一致
p = &add; //这里用函数名(add)也可以返回地址
c = (*p)(2,3);//p(2,3)也可以
printf("%d",c);
void (*ptr)(char*); //因为PrintHello这个函返回的类型是void所以定义指针的时候也应该是void
ptr = PrintHello;
ptr("Tom");
}
此外,在函数与指针中有一个常见的问题
#include<stdio.h>
int* add( int* a, int* b)
{
int c = (*a) + (*b);
return &c;
}
int main(){
int a = 2,b=4;
int* p = add(&a,&b);
printf("Sum = %d \n",*p);
}
此时并不能打印出我们想要的结果,因为add函数在执行完毕以后就被弹出栈空间了,所以被调函数的局部常量并不能返回给主调函数(那块内存已经被释放了)。那么如何解决这个问题呢,此时我们就需要malloc这个库函数派上用场了,它可以堆空间上单独开辟一块空间存放变量,如此一来就再也不担心被弹出栈空间了。
#include<stdio.h>
#include<stdlib.h>
int* add( int* a, int* b)
{
int* c = (int*)malloc(sizeof(int));
*c = (*a) + (*b);
return c;
}
int main(){
int a = 2,b=4;
int* p = add(&a,&b);
printf("Sum = %d \n",*p);
}
现在可以正常输出6!!!需要注意的是,所有在堆上申请的内存都需要用free函数显示地释放!这个示例是需要我们注意,从函数返回指针的时候,一定要注意它们的作用范围。
数组与指针
数组需要注意的是它是默认以 \0 作为定界符的。
例如:
#include<stdio.h>
int main(){
char c[4];
c[0] = 'J';
c[1] = 'h';
c[2] = 'o';
c[3] = 'n';
printf("%s\n",c); //会额外多输出两个乱字符
char b[] = "hello";
printf("Size in bytes = %d\n",sizeof(b)); //打印出来的值是6,因为是以 \0 作为定界符
int len = strlen(b);
printf("Length = %d\n",len);//5 strlen是计算实实在在字符串的长度
}
接下来我们用指针操作数组,重新写一个print函数,打印出数组中的所有元素。
指针操作数组关键是对指针位移的运用
void print(char *c){
int i = 0;
while (*(c+i) != '\0') //指针位移且解引用
{
printf("%c",c[i]);
i++;
}
}
void print(char *c){
int i = 0;
while (*c != '\0') //解引用
{
printf("%c",*c);
c++;
}
}
以上两种写法都是可以的,第二种写法累加对象是指针。
该随笔意在展示指针在函数和数组中的基础应用,还请多多指教。