其他分享
首页 > 其他分享> > C语言入门学习(第二十二天——函数)

C语言入门学习(第二十二天——函数)

作者:互联网

镇楼图

Pixiv:よはく

============

〇、引入函数的原因

当程序规模不断扩大时,主函数会变得冗杂、复杂、难阅读、关联度过高、难修改等问题,这时候引入【函数】来分解程序,提高可读性、效率是非常有必要的。

其他程序员在使用你的函数时只需要了解作用、参数、返回即可。

============

一、函数

①声明函数

编译会从上往下编译,而如果你调用的语句在上面定义函数在下面,则会报错。于是你需要提前声明函数防止报错,告诉编译器“确实有这个函数,只是你还没看到。”

一般声明语句会写在最上面

<类型名> <函数名>(参数列表)
//若不存在返回值,参数最好写void
//声明函数可以只写类型
void test();

int main(){
	test();
}

void test(){
	printf("HelloWorld");
}

②定义函数

<类型名> <函数名>(参数列表){
	<函数体>
}

③调用函数

根据你写的函数按照定义来调用
//声明函数 
void print_C();
 
//定义函数 
void print_C(){
 	printf(" ###### \n");
 	printf("##    ##\n");
 	printf("##      \n");
 	printf("##      \n");
 	printf("##      \n");
 	printf("##    ##\n");
	printf(" ###### \n");
 }
 
int main()
{
//调用函数
	print_C();
    return 0;
}

============

二、extern关键字

extern关键字用于声明全局变量

和声明函数类似,防止报错

int main(){
    extern int a;
    printf("%d\n\a",a);
}
int a = 3;

============

三、作用域

变量被定义到不同位置时,所作用的范围称为作用域。

①代码块作用域block scope

一个代码块{}中定义的变量只能在这代码块中使用

作用域不同的变量允许名字一致

作用域在调用同名变量时会优先考虑这个代码块所在的变量

比如

/*
for、if、switch、函数中定义的变量
也不可在这些代码块以外使用
*/
int main(){
    int a = 2;
    {
        {
            int a = 52;
            printf("%d\n",a);
        }
        printf("%d\n",a);
        int a = 3;
        {
        	int a=1;
        	printf("%d\n",a);
    	}
    	printf("%d\n",a);
    }
    printf("%d\n",a);
}

②文件作用域

在代码块之外的变量、数组、函数等能在这整个文件中使用,则称为具有文件作用域

具有文件作用域的称为全局变量

注:应尽量避免使用全局变量以节省内存、防止污染命名空间、降低程序耦合性。一个好的程序应该要高内聚、低耦合

③原型作用域

声明函数中对于声明的参数的作用域仅限这一行代码。

所以声明时可以不写参数名,参数名也可以不同于原型的参数名

【没什么用】

void f(int,int diff);
void f(int a,int b){
    //...
}

④函数作用域

函数在调用时会产生的作用域,goto语句的标签会被限制在函数内,当函数调用完成后会销毁这个作用域

============

四、定义与声明

定义:

定义是指为某一个对象分配存储空间

声明:

声明是指向编译器表明存在这个变量

定义也可以当作是声明

相同名字只能定义一次,而可以声明多次

============

五、指针参数

函数由参数、返回值、函数体构成

以交换变量的函数为例

void swap(int,int);

void swap(int x,int y){
	int t;
	
	printf("In swap,互换前:x = %d,y = %d\n",x,y);
	t = x;
	x = y;
	y = t;
	printf("In swap,互换后:x = %d,y = %d\n",x,y);
}

int main(){
	int x = 3,y = 5;
	printf("In main,互换后:x = %d,y = %d\n",x,y);
	swap(x,y);
	printf("In main,互换后:x = %d,y = %d\n",x,y);
}

由上面的结果来看,是不符合我们的预期的。

原因在于我们函数内的变量是局部变量无法改变值,需要引入指针或全局变量来达到预期目的

现在再来改一下代码

void swap(int*,int*);

void swap(int *x,int *y){
	int t;
	
	printf("In swap,互换前:x = %d,y = %d\n",*x,*y);
	t = *x;
	*x = *y;
	*y = t;
	printf("In swap,互换后:x = %d,y = %d\n",*x,*y);
}

int main(){
	int x = 3,y = 5;
	printf("In main,互换后:x = %d,y = %d\n",x,y);
	swap(&x,&y);
	printf("In main,互换后:x = %d,y = %d\n",x,y);
}

============

六、传递数组

数组在函数中传递的是首元素的指针,所以即使在函数内改变数组的值,也会改变main中数组的值

数组只有第一维可以省略数量

void get_array(int a[5]);

void get_array(int a[]){
	int i;
	a[3] = 520;
	for (i = 0;i<10;i++){
        printf("a[%d] = %d\n",i,a[i]);
    }
}

int main(){
    int a[10] = {0,1,2,3,4,5,6,7,8,9};
    int i;
    get_array(a);
    printf("\n=========\n");
    for (i = 0;i<10;i++){
        printf("a[%d] = %d\n",i,a[i]);
    }
    return 0;
}

===========

七、指针函数

函数返回类型为指针的函数称为指针函数

char *cstrcat(char*,const char*);

char *cstrcat(char* a,const char* b){
     char* r = strcat(a,b);
    return r;
}

int main(){
	char a[30] = "123456",b[] = "abcdef";
	cstrcat(a,b);
	printf("%s",a);
    return 0;
}

和之前的知识多少有些重复,比较简单,但需要注意一个点!

不要返回局部变量的指针

根据作用域我们可以得知,定义指针的变量是一个在函数作用域内的变量。

当你返回指针后这个变量也同时被销毁,而返回到的指针因为原本指向的内容也被销毁自然会有八嘎(bug)

以下这段代码明显会出错

(编译器只会警告,不确定你是要这个指针的返回值还是所指向的内容)

char *cstrcat(void);

char *cstrcat(void){
    char str[10] = "ABCDEFG";
    return str;
}

int main(){
	printf("%s",cstrcat());
    return 0;
}

============

八、函数指针

int (*p)(int,int)

这是不是感觉和数组指针很像呢?本质上就是优先级的不同而导致的不同的结果。

那么函数指针有什么作用呢?

函数在定义后会存在一个地址,这个地址称为【入口地址】,而这个地址的值就是函数名。

现在你多了一种方式去调用函数

int square(int);

int square(int num){
 	return num*num;
}

int main(){
    int num;
    scanf("%d",&num);
    int (*p)(int) = square;
    printf("%d",(*p)(num));
}

============

九、return

return关键字用来返回函数的值并结束本次函数的调用

只能返回一个值

============

总结

现在可以使用函数去简化main函数,参数可以用变量、指针、数组,返回值可以是变量、常量、指针,调用方式也可以使用指针来调用.

另外可以看看stdarg.h

还可以看看如何用函数传递函数

这个模块能较弱地实现一个函数带可变数量的参数

参考资料

https://fishc.com.cn

http://www.cplusplus.com/reference

https://www.icourse163.org/course/ZJU-200001

http://c.biancheng.net/

标签:第二十二,函数,int,void,C语言,作用域,printf,main,入门
来源: https://www.cnblogs.com/AlienfronNova/p/14454208.html