详解C语言之函数

目录
  • 函数的调用
    • 函数调用方式
    • 函数嵌套调用
    • 递归调用
  • 内部函数与外部函数
    • 内部函数
    • 外部函数
  • 局部变量与全局变量
    • 局部变量
    • 全局变量
  • 总结

函数的调用

函数调用方式

  • 函数语句调用
  • 函数表达式调用
  • 函数参数调用

sum(); //函数语句调用

result = average * sum(a); //函数表达式调用

此时函数名出现在表达式中,其返回值将作为表达式的算数参与计算。

result = sum(sum1(a)); //函数参数调用

此时函数名出现在另一个函数的参数中,其返回值将作为实参赋值给外函数的形参。

函数嵌套调用

首先在C语言中不允许函数嵌套定义,也就是不许在一个函数内定义一个新函数。

但是C语言允许函数嵌套调用。

void a()
{
        printf("sth");
}
void b()
{
        printf("sth2");
        a();
}

递归调用

C语言的函数都支持递归,也就是说,每个函数都可以直接或间接地调用自己。

递归实现的原因是函数的每个执行过程在栈中都有自己的形参和局部变量的副本,这些副本相对独立。

假定某个函数调用了一个被调用的函数,再假定被调用的函数反过来调用了调用函数,那么第二个函数就称为调用函数的递归。

使用函数的递归需要两个先决条件,即递推关系和结束条件。

写个简单的函数递归:

#include<stdio.h>
void number(int a)
{
	int num = a;
	printf("输入一个正数:");
	scanf("%d",&num);
	if(num <= 0)
	{
		number(num);
	}
	else
	{
		printf("这个正数是:%d",num);
	}
}
int main()
{
	int a;
	number(a);
	return 0;
}

内部函数与外部函数

函数是C语言程序中的最小实现单位,我们可以把一个函数或者多个函数保存为一个文件,这个文件被称为源文件。

我们在定义一个函数后,该函数便可被其他函数所调用。

但当一个源程序由多个源文件组成时,我们可以指定函数不能被其他文件调用,这时C语言的函数便分为两大类,内部函数与外部函数。

内部函数

当某一个函数只能被其所在源文件调用时,他便被称为内部函数,也叫做静态函数。

当一个函数是内部函数时,他便只局限与其所在源文件中,其他源文件就可以有同名函数,并且他们之间互不干扰。

static关键字可以将原来的函数修饰成普通函数。

static 返回值类型 函数名(参数列表)

static int number(int a)

外部函数

与内部函数相反,外部函数是可以被其他源文件调用的。

外部函数使用extern关键字进行修饰。

一般来说,定义函数时如果没有使用extern关键字,则将默认该函数为默认函数,换言之,extern可以省略。

extern 返回值类型 函数名(参数列表)

extern in number(int a)

局部变量与全局变量

“作用域”:他决定了程序中哪些语句可用哪些不可用,换言之,就是程序的可见性。作用域包括局部作用域和全局作用域。

局部变量具有局部作用域,全局变量具有全局作用域。

局部变量

在一个函数内定义的变量称为局部变量,我们使用的大多数变量都是局部变量,这些变量的声明在函数内部,无法被其他函数使用。

函数的形式参数也属于局部变量,只作用于函数内的所有语句块。

一般来说,一个局部变量的作用域可以由包含该变量的一对大括号所决定。

全局变量

与局部变量相对,在函数外部进行声明定义的变量,称为全局变量。

全局变量不属于某一个函数,而属于整个源文件。如果要在其他文件中使用该变量,则需先用extern关键字进行引用修饰。

全局变量的作用是增加函数间数据联系的通道。如果在一个函数中改变了全局变量的值,就能影响到其他函数,这便打通了不同函数之间的通道。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C语言内存操作函数详解

    目录 头文件:#include<memory.h> 2.memmove 3.memcmp 4.memset 总结 头文件:#include<memory.h> 1.memcpy 作用:内存拷贝 函数原型: void *memcpy( void *dest, const void *src, size_t count ); 使用: 使用格式:memcpy(目的地,原,想操作内存大小(单位字节)) 把 "参数2" 起始的 "参数3" 个字节 内容

  • C语言可变参数函数详解

    目录 C语言可变参数函数 总结 C语言可变参数函数 C 语言允许定义参数数量可变的函数,这称为可变参数函数(variadic function).这种函数需要固定数量的强制参数(mandatory argument),后面是数量可变的可选参数(optional argument). 这种函数必须至少有一个强制参数.可选参数的类型可以变化.可选参数的数量由强制参数的值决定,或由用来定义可选参数列表的特殊值决定. C 语言中最常用的可变参数函数例子是 printf()和 scanf().这两个函数都

  • C语言函数栈帧详解

    目录 前言 一.函数栈帧是什么? 二.栈帧准备知识 1.内存分区 2.什么是栈? 三.详解栈帧创建与销毁全过程 调用函数之前: 将传入函数的值放入栈中 函数执行: 1.保护当前ebp 2.创建所需调用函数的栈帧空间 3.保存局部变量 4.参数运算 函数返回: 1.存储返回值 2.销毁空间 3.ebp回上一栈帧栈底 4.销毁形参 5.main函数拿到返回值 总结 前言 在c语言中我们会将一些功能单独写成一个函数,以供主函数调用,在表面来看调用的过程就是写出一个函数后,只需要在调用时中通过函数名将实

  • 关于C语言qsort函数详解

    目录 C语言qsort函数详解 一.qsort函数是什么 二.使用qsort排序-以升序为例 1.整形数组排序 2.字符数组排序 3.字符指针数组排序 4.结构体数组排序 5.浮点型数组排序 三.使用冒泡排序思想模拟实现qsort函数 1.什么是冒泡排序 2.冒泡排序代码 3. 使用冒泡排序思想模拟实现qsort函数 C语言qsort函数详解 一.qsort函数是什么 我们可以使用  搜索库函数网址或者MSDN软件进行查找. qsort()函数:快速排序的函数  -引用stdlib.h头文件 参

  • C语言函数指针详解

    目录 Introduction 函数指针 Function Pointers Exercise 1:qsort中的函数指针 Exercise 2: 总结 Introduction 上一个lab的主要内容为__data pointer__(指向数据的指针)可能在Linux系统中造成的__segmentation fault__.本次lab将考虑__function pointer__(指向函数/代码的指针)可能造成的错误:segfault或其他exceptions. 函数指针 Function P

  • 详解C语言gets()函数与它的替代者fgets()函数

    在c语言中读取字符串有多种方法,比如scanf() 配合%s使用,但是这种方法只能获取一个单词,即遇到空格等空字符就会返回.如果要读取一行字符串,比如: I love BIT 这种情况,scanf()就无能为力了.这时我们最先想到的是用gets()读取. gets()函数从标准输入(键盘)读入一行数据,所谓读取一行,就是遇到换行符就返回.gets()函数并不读取换行符'\n',它会吧换行符替换成空字符'\0',作为c语言字符串结束的标志. gets()函数经常和puts()函数配对使用,puts

  • 详解C语言fscanf函数读取文件教程及源码

    目录 第一部分:问题和结论 fscanf 函数的原型是: 第二部分:实验代码 实验代码: fscanf 函数用于格式化读入文件中数据,可以大大提高读取文件的效率.这次笔者将最近使用该函数的一些经验记录下来. 第一部分:问题和结论 fscanf 函数的原型是: int fscanf(FILE* stream, const char* format, [argument...]); fscanf 函数与 scanf 函数用法类似,只不过前者用于读取文件流的数据而已.至于 fscanf 的基础用法我就

  • 详解C语言sscanf()函数、vsscanf()函数、vscanf()函数

    C语言sscanf()函数:从字符串中读取指定格式的数据 头文件: #include <stdio.h> sscanf()函数用于从字符串中读取指定格式的数据,其原型如下: int sscanf (char *str, char * format [, argument, ...]); [参数]参数str为要读取数据的字符串:format为用户指定的格式:argument为变量,用来保存读取到的数据. [返回值]成功则返回参数数目,失败则返回-1,错误原因存于errno 中. sscanf()

  • 实例详解易语言返回函数

    返回()是易语言的重要函数,很多函数都有返回值,就是用这个函数返回. 非无私奉献,拒绝看经验不回复,学懂了记得按照下面做: 具体操作请看图. 1.易语言新建一个windows窗口 点击进入代码编辑区 2.我们首先定义一个变量a 整数型 3.然后我们输入计次循环首 这个具体用法请看 易语言计次循环首函数实例讲解 4.我们在循环里输入函数 如果真(a>5) 这个具体用法请看 易语言如果真函数用法 5.然后我们在最后位置输入 调试输出(1) 运行结果为1 6.我们在如果真下面输入 返回() 发现没有结

  • 详解R语言plot函数参数合集

    最近用R语言画图,plot 函数是用的最多的函数,而他的参数非常繁多,由此总结一下,以供后续方便查阅. plot(x, y = NULL, type = "p", xlim = NULL, ylim = NULL, log = "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL, ann = par("ann"), axes = TRUE, frame.plot = axes, panel.

  • 详解C语言之函数

    目录 函数的调用 函数调用方式 函数嵌套调用 递归调用 内部函数与外部函数 内部函数 外部函数 局部变量与全局变量 局部变量 全局变量 总结 函数的调用 函数调用方式 函数语句调用 函数表达式调用 函数参数调用 sum(); //函数语句调用 result = average * sum(a); //函数表达式调用 此时函数名出现在表达式中,其返回值将作为表达式的算数参与计算. result = sum(sum1(a)); //函数参数调用 此时函数名出现在另一个函数的参数中,其返回值将作为实参

  • 详解C语言函数返回值解析

    详解C语言函数返回值解析 程序一: int main() { int *p; int i; int*fun(void); p=fun(); for(i=0;i<3;i++) { printf("%d\n",*p); p++; } return 0; }; int* fun(void) { static int str[]={1,2,3,4,5}; int*q=str; return q; } //不能正确返回 虽然str是在动态变量区,而该动态变量是局部的,函数结束时不保留的.

  • 详解C语言用malloc函数申请二维动态数组的实例

    详解C语言用malloc函数申请二维动态数组的实例 C语言在程序运行中动态的申请及释放内存十分方便,一维数组的申请及释放比较简单. Sample one #include <stdio.h> int main() { char * p=(char *)malloc(sizeof(char)*5);//申请包含5个字符型的数组 free(p); return 0; } 是否申请二维动态内存也如此简单呢?答案是否定的.申请二维数组有一下几种方法 Sample two /* 申请一个5行3列的字符型

  • 详解C语言常用的一些转换工具函数

    1.字符串转十六进制 代码实现: 2.十六进制转字符串 代码实现: 或者 效果:十六进制:0x13 0xAA 0x02转为字符串:"13AAA2" 3.字符串转十进制 代码实现: 第一种,如果带负号 这个就是atoi函数的实现: 效果:字符串:"-123" 转为 -123 第二种,如果不带负号: 效果:字符串:"123" 转为 123 第三种:包含转为浮点数: 效果:字符串:"123.456" 先转为 123456,然后除以1

  • 详解Go语言Slice作为函数参数的使用

    目录 前言 问题与解析 典型问题 其它疑问1 其它疑问2 结论 参考链接 前言 首先要明确Go语言中实质只有值传递,引用传递和指针传递是相对于参数类型来说. 个人认为上诉的结论不对,把引用类型看做对指针的封装,一般封装为结构体,结构体是值类型,所以感觉都是值传递.不然我感觉其它语言实质不也都是值传递?不过我刚学Go,可能还没完全弄懂,这个有问题可以互相讨论下. Go语言中的值类型:int.float.bool.array.sturct等,声明一个值类型变量时,编译器会在栈中分配一个空间,空间里存

随机推荐